.net核心控制台应用程序作为Windows服务-是否可以在不使用Kill()方法的情况下安全地终止已启动进程的执行?

时间:2019-05-14 09:40:21

标签: c# process windows-services asp.net-core-2.0 asp.net-core-2.2

我有一个dotnet core 2.2控制台应用程序。
我将其托管为Windows服务。(服务名称:“ MyService1”)
“ MyService1”启动另一个dotnet核心WebAPI。
问题是,当“ MyService1”停止时,如何安全地终止WebAPI进程?

这是我尝试执行的操作,但仍可以在任务管理器中看到该过程。

public class MyService : IHostedService, IDisposable
{
    private Timer _timer;
    static Process webAPI;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _timer = new Timer(
            (e) => StartChildProcess(),
            null,
            TimeSpan.Zero,
            TimeSpan.FromMinutes(1));

        return Task.CompletedTask;
    }

    public void StartChildProcess()
    {
        try
        {
            webAPI = new Process();
            webAPI.StartInfo.UseShellExecute = false;
            webAPI.StartInfo.FileName = @"C:\Project\bin\Debug\netcoreapp2.2\publish\WebAPI.exe";
            webAPI.Start();
        }
        catch (Exception e)
        {
            // Handle exception
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        // TODO: Add code to stop child process safely
        webAPI.Close();  

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

是否可以不使用Kill()方法来做到这一点?

2 个答案:

答案 0 :(得分:1)

我不确定您是从哪里开始其他WebAPI进程的,但您有2个选择:

  1. 从您的ProcessExit文件注册到Program.cs事件并关闭WebAPI 在那里处理,就像这样:

    class Program
    {
        static Process webAPI;
    
        static async Task Main(string[] args)
        {
            AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
    
            webAPI = new Process
            {
                StartInfo = new ProcessStartInfo("dotnet")
                {
                    UseShellExecute = false,
                    CreateNoWindow = true,
    
                    //If you want to run as .exe
                    FileName = @"C:\Project\bin\Debug\netcoreapp2.2\publish\WebAPI.exe",
    
                    //If you want to run the .dll
                    WorkingDirectory = "C:/Project/publish",
                    Arguments = "WebAPI.dll"
                }
            };
            using (webAPI)
            {
                webAPI.Start();
                webAPI.WaitForExit();
            }
        }
    
        static void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            webAPI.Close();
        }
    }
    
  2. 将服务进程ID传递到WebAPI进程并从那里对其进行监视,如下所示:

    class Program
    {
        static async Task Main(string[] args)
        {
            try { }
            catch { }
            // Make sure you use a finally block.
            // If for any reason your code crashes you'd still want this part to run.
            finally
            {
                if (int.TryPasre(args[X], out parentProcessId))
                    MonitorAgentProcess(parentProcessId);
            }
        }
    
        static void MonitorAgentProcess(int parentProcessId)
        {
            try
            {
                Process process = Process.GetProcessById(parentProcessId);
                Task.Run(() => process.WaitForExit())
                    .ContinueWith(t => Environment.Exit(-1));
            }
            catch {}
        }
    }
    

答案 1 :(得分:0)

您遇到的问题是您的webAPI任务实际上是一个单独的EXE,没有集成到服务中。除非该服务具有与之交互并请求正常关闭的方式,否则您将不得不在绝对不干净的庄园中终止EXE进程。