예제 #1
0
        /// <summary>
        /// End the task gracefully if possible, forcefully if necessesary.
        /// Disposes both the pipe and the process when done.
        /// Wait up to timeoutMs milliseconds for the application to close itself.
        /// This is optionally a blocking call, but can also be a "fire and forget"
        /// function by setting block=false.
        /// </summary>
        void TerminateProcess(ref WtsProcess refProcess, ref ProcessManager refManager, bool block)
        {
            var process = refProcess;
            var manager = refManager;

            refProcess = null;
            refManager = null;

            // Quick exit if process is not running
            if (process == null || !process.IsRunning)
            {
                if (process != null)
                {
                    process.Dispose();
                }
                if (manager != null)
                {
                    manager.Close();
                }
                return;
            }

            // Force kill the process if the pipe is not connected
            if (manager == null || !manager.IsConnected)
            {
                // NOTE: Pipe was connected by WaitForPipeCommand
                Log.Write("FORCE KILL process because pipe is not connected: Pipe=" + manager.PipeName);
                process.Terminate(0);
                process.Dispose();
                if (manager != null)
                {
                    manager.Close();
                }
                return;
            }

            // Send the process a request to close in background thread
            Log.Write("Closing process: Pipe=" + manager.PipeName);
            Task.Run(async() =>
            {
                try
                {
                    await manager.SendCommandAsync(ProcessManager.COMMAND_CLOSE);
                }
                catch (Exception ex)
                {
                    Log.Write("Exception sending close command", ex);
                }
            });

            // Wait for it to exit gracefully, but kill it if still running after the timeout
            var task = Task.Run(async() =>
            {
                try
                {
                    // Give it up to one second to kill itslef
                    var now = DateTime.Now;
                    while ((DateTime.Now - now).TotalMilliseconds < PROCESS_TERMINATE_TIMEOUT_MS && process.IsRunning)
                    {
                        await Task.Delay(10);
                    }

                    if (process.IsRunning)
                    {
                        Log.Write("FORCE KILL process after sending cose command: Pipe=" + manager.PipeName);
                        process.Terminate(0);
                    }
                    else
                    {
                        Log.Write("Process closed gracefully: Pipe=" + manager.PipeName);
                    }
                    process.Dispose();
                    manager.Close();
                }
                catch (Exception ex)
                {
                    Log.Write("Cant kill process: Pipe=" + manager.PipeName, ex);
                }
            });

            if (block)
            {
                task.Wait();
            }
        }