在ASP.NET Core Process中创建的子进程在退出时被杀死

时间:2019-01-09 08:21:07

标签: c# .net asp.net-web-api

我正在使用Process类在ASP.NET Core(.NET Framework)中产生一个子进程:

var process = new Process
            {
                StartInfo = new ProcessStartInfo(executableDir)
                {
                    Arguments = commandDefinition.CommandDef.ArgumentsAsString,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = _contentPath,
                },
            };

process.Start()

据我了解,父进程(ASP.Net Core)被杀死时,子进程应保持活动状态。我已经使用两个控制台应用程序测试了此行为,并且杀死父进程之后,子进程再也不会被杀死。 但是,当我在ASP.NET Core中生成新进程时,在以下情况下子进程会被杀死:

  • IIS回收应用程序。
  • MSDeploy发布新版本的ASP.NET Core应用。
  • 使用dotnet watch时,在 代码更改。

只有通过任务管理器杀死父母,它不会被杀死。(经过一些测试,情况并非总是如此)

从上面我怀疑在ASP.NET Core中有一种机制可以在成功退出时杀死所有子进程。是否记录在某处?有办法避免吗?我找不到有关此类行为的任何信息。

编辑: 复制实际上很简单。

  1. 创建ASP.NET Core项目(.NET Framework或.NET Core,无关紧要)
  2. 将以下代码添加到您的Startup类中
  3. 启动网络应用。它将托管在IIS Express下。计算过程将开始。现在,要么通过任务管理器杀死您的应用程序,要么通过IIS Express任务栏图标将其关闭。
  4. Calc进程将被杀死。 (有时您需要尝试刷新您的离线网页)
 var process = new Process
 {
      StartInfo = new ProcessStartInfo("calc.exe")
      {
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true,
      },
 };
 process.Start();

Edit2:问题似乎出在IIS中。我在launchSettings.json中有两个配置文件。如果我使用IISExpress运行它,它将关闭,但是使用第二个它时,它仍然存在。

"IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/values",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApplication3Core": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/values",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:52135/"
    }

Edit4:

我用过程监视器做了一些研究,这是输出:

ss1

ss2

ss3

正如您在ss1中看到的那样,iisexpress有一个“进程退出”操作,因此有许多无关紧要的日志,一段时间之后,calc.exe就有了进程退出。与正常出口没有什么不同。唯一的区别是后一个日志显示“ CloseFile”和我的Web应用程序的路径,我不知道它的实际含义。 肯定是iis杀死了calc.exe。我有IIS Express 10.0.14358版本(服务器版本也为10)

2 个答案:

答案 0 :(得分:4)

修改

  

解决方案不适用于notepad.exe-我将尝试查看是否存在   基于Simon的回答的任何选项,为什么会出现这种行为

旧答案(将被删除)

现在我必须洗手才能编写这段代码,但是如果您在上下文中需要这样做,我想您可以解决此限制。我建议不要运行外部流程,尤其是 从“ Web服务器”。它自找麻烦。某些恶意人员替换进程,升级凭据,由于语法更改而导致的意外行为仅举几例。

无论如何,这可能对您有用(在它们之间插入cmd.exe,以试图打破孩子与父母之间的关系):

var process = new Process
{
  StartInfo = new ProcessStartInfo 
      { 
         FileName ="cmd.exe",  
         Arguments = "/c calc.exe", 
         WindowStyle =  ProcessWindowStyle.Hidden
      }
};

process.Start();

答案 1 :(得分:4)

正如我在评论中所说,在Job Object中有一个out-of-process scenario由ASP.NET核心创建。相关的源代码部分在这里:

https://github.com/aspnet/AspNetCore/blob/master/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/serverprocess.cpp#L89

HRESULT
SERVER_PROCESS::SetupJobObject(VOID)
{
    HRESULT                                 hr = S_OK;
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION    jobInfo = { 0 };

    if (m_hJobObject == NULL)
    {
      ....
            jobInfo.BasicLimitInformation.LimitFlags =
                JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            if (!SetInformationJobObject(m_hJobObject,
                JobObjectExtendedLimitInformation,
                &jobInfo,
                sizeof jobInfo))
            {
                hr = HRESULT_FROM_WIN32(GetLastError());
            }
        }
    }

    return hr;
}

根据文档JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE

  

导致与作业关联的所有进程在   该作业的最后一个手柄已关闭。

如果您进一步挖掘源代码,它似乎不是可选的。

现在,如果您复制自己的步骤,则实际上您可以自己看到。使用Process Explorer,然后导航到您的dotnet.exe进程,它将显示以下内容:

enter image description here

  • 注1:实际上calc.exe仍然有效(至少在我的Windows 10安装中,因为它现在是WinRT应用程序,所以它最终不会成为dotnet.exe的子项),这就是我使用{{ 1}}
  • 注释2:notepad.exe也创建了一个作业对象,但是将其配置为可以脱离,这意味着它不会杀死子进程。
  • 注释3:如果您从Visual Studio运行(而不是我的屏幕截图),则可能会看到iisexpress.exeVSIISExeLauncher.exe之间的中介iisexpress.exe过程。这也创建了一个“关闭时杀死”的作业对象,以增加混乱...