C# 父进程终止时如何终止子进程
任务:如果父进程终止,则自动终止所有子进程。父进程不仅可以以正确的方式终止,还可以通过例如在 ProcessExplorer 中终止来终止。 我该怎么做呢?
С主题中的类似问题建议使用 Job 对象。如何在C#中使用它而不导出外部DLL?
我尝试使用作业对象。但此代码无法正常工作:
var job = PInvoke.CreateJobObject(null, null);
var jobli = new PInvoke.JOBOBJECT_BASIC_LIMIT_INFORMATION();
jobli.LimitFlags = PInvoke.LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_PRIORITY_CLASS
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_TIME
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_MEMORY;
var res = PInvoke.SetInformationJobObject(job, PInvoke.JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation, jobli, 48);
if (!res)
{
int b = PInvoke.GetLastError();
Console.WriteLine("Error " + b);
}
var Prc = Process.Start(...);
PInvoke.AssignProcessToJobObject(job, Prc.Handle);
PInvoke.SetInformationJobObject 返回错误。 GetLastError 返回错误 24。 但是,PInvoke.AssignProcessToJobObject 可以工作,并且子进程已添加到作业队列(我可以在 ProcessExplorer 中看到它)。但是,因为 PInvoke.SetInformationJobObject 不起作用 - 当我杀死父进程时,生成的进程仍保持活动状态。
这段代码中有什么不正确的地方?
Task: Auto kill all child processes if parent process terminate. Parent procees can be terminated not only in correct way, but also by killing in ProcessExplorer, for example.
How can I do it?
Similar question in С topic advice to use Job objects. How to use it in C# without exporting external DLL?
I tried to use Job Objects. But this code doesn't work properly:
var job = PInvoke.CreateJobObject(null, null);
var jobli = new PInvoke.JOBOBJECT_BASIC_LIMIT_INFORMATION();
jobli.LimitFlags = PInvoke.LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_PRIORITY_CLASS
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_TIME
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
| PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_MEMORY;
var res = PInvoke.SetInformationJobObject(job, PInvoke.JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation, jobli, 48);
if (!res)
{
int b = PInvoke.GetLastError();
Console.WriteLine("Error " + b);
}
var Prc = Process.Start(...);
PInvoke.AssignProcessToJobObject(job, Prc.Handle);
PInvoke.SetInformationJobObject returns with error. GetLastError returns error 24.
However, PInvoke.AssignProcessToJobObject works and child process added to Job Queue (I can see it in ProcessExplorer). But, because PInvoke.SetInformationJobObject don't work - spawned process stay alive when I kill parent one.
What do I have incorrect in this code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
要在 Windows 上终止进程树,仅给出父进程或进程 ID,您需要遍历进程树。
为此,您需要一种方法来获取给定进程的父进程 ID。
一旦掌握了这一点,实际上杀死这棵树并不难。
To kill a process tree on windows, given only the parent process or process id, you'll need to walk the process tree.
For that, you'll need a way to get the parent process id for a given process.
Once you have that, actually killing the tree is not hard.
我尝试了上面的代码,确实,它不起作用,抱怨尺寸不好。其原因是所使用的结构根据主机平台的不同而改变大小;原始代码片段(在十几个网站上可见)假设是 32 位应用程序。
将结构切换到此(注意 IntPtr 调整大小成员),它将起作用。至少对我来说是这样。
I tried the code above and indeed, it does not work, complaining of a bad size. The reason for this is that the structure used changes size depending on the host platform; the original code fragment (seen on a dozen websites) assumes a 32 bit application.
Switch the structure to this (note the IntPtr resizing members) and it will work. At least it did for me.
您可以将父进程的 ProcessID 作为参数传递给子进程。然后子进程将负责时不时地检查父进程是否仍在运行。 (通过调用
Process.GetProcessById
。)跟踪父进程是否存在的另一种方法是使用
Mutex
同步原语。父应用程序最初将创建一个全局互斥体,其名称为子应用程序所知。孩子们可以不时检查互斥体是否仍然存在,如果不存在则终止。 (一旦父进程关闭,互斥体将被系统自动销毁,无论其关闭方式如何。)
You can pass
ProcessID
of the parent process as an argument to the child process. And then child processes will be responsible for checking from time to time whether the parent process still running. (By callingProcess.GetProcessById
.)Another way to track existence of the parent process is to use
Mutex
synchronization primitive.Parent application will initially create a global mutex with the name known by children. Children can check from time to time whether the mutex still exists and terminate if not. (Once the parent process is closed the mutex will be destroyed by the system automatically, regardless of the way it way closed.)
你注意过错误代码吗?错误 24 是
ERROR_BAD_LENGTH
,这可能意味着 48 不是正确的结构长度。我认为是 44,但您应该执行sizeof
来确定。Did you pay attention to the error code? Error 24 is
ERROR_BAD_LENGTH
, which probably means that 48 isn't the right length of the structure. I think it's 44, but you should do asizeof
to be sure.当父进程关闭时,Windows 不会强制子进程关闭。当您在任务管理器或进程资源管理器等工具中选择“杀死树”时,该工具实际上会找到所有子进程并将其一一杀死。
如果您想确保在应用程序终止时清除子进程,您可以创建一个实现 IDisposable 的 ProcessManager 类,该类实际创建进程,跟踪它们的实例并在 Dispose 上对每个进程调用 Kill,例如
Windows does not force child processes to close when a parent process closes. When you select "Kill Tree" in a tool like Task Manager or Process explorer, the tool actually finds all child processes and kill them one by one.
If you want to ensure that child processes are cleaned when your application terminates, you can create a ProcessManager class that implements IDisposable that actually creates the processes, keeps track of their instances and calls Kill on each one of them on Dispose, e.g.