父进程和子进程的关系

4
我有一个打开子进程的父进程。我需要在父进程不再运行时执行一些功能。
如何知道父进程已经停止运行?因为它可能会被强制终止,所以我不想在关闭事件上发送信号给我的子进程以执行某些功能。
或者只是像这样寻找我的父进程:
在父进程中进行此操作,并将其传递给子进程 Process.GetCurrentProcess().Id,并在子进程中每隔几毫秒检查一次。
Process localById = Process.GetProcessById(1234);

有什么想法?建议...

2
嗯...通常是父进程。除非你真的认识你的进程的性别。干杯。 - Aoi Karasu
@AOI Karasu:哈哈,说得好。我顺手改了一下(如果性别很重要,请 Night Walker 撤回我的更改)。 - Abel
我刚刚发布了一个针对.NET的子进程库 http://childprocess.codeplex.com/ - Thomas Maierhofer
4个回答

5

以下是一个简单的示例,演示如何使用Process.WaitForExit检查已在命令行中传递其ID的父进程:

using System;
using System.Diagnostics;
using System.Threading;

class Program
{
    static AutoResetEvent _autoResetEvent;

    static void Main(string[] args)
    {
        int parentProcessId = int.Parse(args[0]);

        _autoResetEvent = new AutoResetEvent(false);

        WaitCallback callback = delegate(object processId) { CheckProcess((int)processId); };
        ThreadPool.QueueUserWorkItem(callback, parentProcessId);

        _autoResetEvent.WaitOne();
    }

    static void CheckProcess(int processId)
    {
        try
        {
            Process process = Process.GetProcessById(processId);
            process.WaitForExit();
            Console.WriteLine("Process [{0}] exited.", processId);
        }
        catch (ArgumentException)
        {
            Console.WriteLine("Process [{0}] not running.", processId);
        }

        _autoResetEvent.Set();
    }
}

可以像这样使用Process.Exited事件:

using System;
using System.Diagnostics;
using System.Threading;

class Program
{
    static AutoResetEvent _autoResetEvent;

    static void Main(string[] args)
    {
        int parentProcessId = int.Parse(args[0]);
        Process process = Process.GetProcessById(parentProcessId);
        process.EnableRaisingEvents = true;
        process.Exited += new EventHandler(process_Exited);

        _autoResetEvent = new AutoResetEvent(false);
        _autoResetEvent.WaitOne();
    }

    static void process_Exited(object sender, EventArgs e)
    {
        Console.WriteLine("Process exit event triggered.");
        _autoResetEvent.Set();
    }
}

请注意,这两个示例中 AutoResetEvent 的目的仅是防止主线程退出。在 Windows Forms 应用程序中,您不需要使用它,因为您的程序将在消息循环中,并且只有在关闭它时才会退出。

我已经使用了Process.Exited示例。非常感谢您的好解释。 - Night Walker

4

底层的Win32进程句柄是可等待的,当进程退出时将被发出信号。

在本地代码中:

DWORD res = WaitForSIngleObject(hProcess, INFINITE);
if (res == WAIT_OBJECT_0) {
  // process has exited.
}

在本地代码中,您需要创建一个自定义的 WaitHandle 子类型来处理进程句柄,或者使用 P/Invoke。P/Invoke 的缺点是难以组合(使用 WaitForMultipleObjects 进行多个等待),因此您不能将一个线程专门用于等待一个事物。
感谢 0xA3:只需使用 Process.WaitForExit 即可(有一个带超时参数的重载版本可以避免无限等待,并且不要在 UI 线程上执行此操作)。

抱歉,我不是很想去使用本地代码。 - Night Walker
1
@夜行者:不需要这样做,只需使用Process.WaitForExit,最好在单独的线程中执行。 - Dirk Vollmar
但我需要在子进程中等待父进程。不确定如何使用Process.WaitForExit。 - Night Walker
1
@NightWalker:要么父进程通过命令行将其ID传递给子进程,要么使用WMI和Win32_Process请求子进程并使用父进程ID属性。一旦您获得了父进程的ID,就可以使用Process.GetProcessById()获取一个进程实例。 - Richard

1

当父进程启动子进程时,通过命令行参数将父进程的ID传递给子进程。

然后在子进程中,使用Process.GetProcessById(int)获取父进程,并使用Process.WaitForExit()。或者,您可以使用Process.Exited事件在父进程退出时收到通知(记得将Process.EnableRaisingEvents设置为true,否则事件不会被触发)。


0
我制作了一个子进程管理库,其中父进程和子进程由双向WCF管道监视。如果任一进程终止,则会通知另一个进程。 还有一个调试助手可用,它会自动将VS调试器附加到启动的子进程。
双向WCF通道是可扩展的,您可以处理进程启动和进程终止事件。
项目网站:

http://www.crawler-lib.net/child-processes

NuGet包:

https://www.nuget.org/packages/ChildProcesses https://www.nuget.org/packages/ChildProcesses.VisualStudioDebug/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接