我正在使用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中生成新进程时,在以下情况下子进程会被杀死:
只有通过任务管理器杀死父母,它不会被杀死。(经过一些测试,情况并非总是如此)
从上面我怀疑在ASP.NET Core中有一种机制可以在成功退出时杀死所有子进程。是否记录在某处?有办法避免吗?我找不到有关此类行为的任何信息。
编辑: 复制实际上很简单。
Startup
类中 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中看到的那样,iisexpress有一个“进程退出”操作,因此有许多无关紧要的日志,一段时间之后,calc.exe就有了进程退出。与正常出口没有什么不同。唯一的区别是后一个日志显示“ CloseFile”和我的Web应用程序的路径,我不知道它的实际含义。 肯定是iis杀死了calc.exe。我有IIS Express 10.0.14358版本(服务器版本也为10)
答案 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核心创建。相关的源代码部分在这里:
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进程,它将显示以下内容:
calc.exe
仍然有效(至少在我的Windows 10安装中,因为它现在是WinRT应用程序,所以它最终不会成为dotnet.exe的子项),这就是我使用{{ 1}} notepad.exe
也创建了一个作业对象,但是将其配置为可以脱离,这意味着它不会杀死子进程。iisexpress.exe
和VSIISExeLauncher.exe
之间的中介iisexpress.exe
过程。这也创建了一个“关闭时杀死”的作业对象,以增加混乱...