监控另一个应用程序,如果它关闭了,则关闭我的应用程序(无需轮询)c#

3

你好,我想要“hook”另一个应用程序,以便在它关闭时关闭我的应用程序。

我不想轮询运行的进程,因为这似乎是不必要的繁琐操作,如果我想实时响应。

我相信应用程序在创建或关闭窗口时会发送消息,那么如何钩取这些消息以知道何时关闭应用程序呢?

例如,假设我的应用程序加载并检查正在运行的进程,以确保记事本已加载,如果是这样,它将保持加载状态,直到记事本关闭。当记事本关闭时,我的应用程序将某种方式知道这一点并退出...

如果可能的话,怎么实现呢?

它需要在xp,vista和win7上工作。

2个回答

9
如果您拥有正在运行应用程序的进程实例,则可以使用Process.WaitForExit,该方法将阻塞直到进程关闭。当然,您可以将WaitForExit放在另一个线程中,以便您的主线程不会被阻塞。
以下是一个示例,不使用单独的线程:
Process[] processes = Process.GetProcessesByName("notepad");
if (processes.Length > 0)
{
  processes[0].WaitForExit();
}

这里是一个使用线程监控进程的简单版本。

public static class ProcessMonitor
{
  public static event EventHandler ProcessClosed;

  public static void MonitorForExit(Process process)
  {
    Thread thread = new Thread(() =>
    {
      process.WaitForExit();
      OnProcessClosed(EventArgs.Empty);
    });
    thread.Start();      
  }

  private static void OnProcessClosed(EventArgs e)
  {
    if (ProcessClosed != null)
    {
      ProcessClosed(null, e);
    }
  }
}

下面的控制台代码是如何使用上述内容的示例。当然,在WPF或WinForms应用程序中同样适用,但请记住,对于UI,您不能直接从事件回调更新UI,因为它在与UI线程分开的线程中运行。这里有很多关于如何从非UI线程更新WinForms和WPF UI的示例,不要忘了哦。
static void Main(string[] args)
{
  // Wire up the event handler for the ProcessClosed event
  ProcessMonitor.ProcessClosed += new EventHandler((s,e) =>
  {
    Console.WriteLine("Process Closed");
  });

  Process[] processes = Process.GetProcessesByName("notepad");
  if (processes.Length > 0)
  {
    ProcessMonitor.MonitorForExit(processes[0]);
  }
  else
  {
    Console.WriteLine("Process not running");        
  }
  Console.ReadKey(true);
}

2
@SaeedAlg,WaitForExit在进程的WaitHandle上内部调用WaitOne,它实际上是ProcessWaitHandle的一个实例。因此,基本上使用操作系统功能等待进程句柄在进程关闭时变为已发信号状态。 - Chris Taylor
嗨,Chris,谢谢你。我是C#的新手,到目前为止一直避免使用多线程!我猜现在我需要去看看了... 有没有可能告诉我如何在另一个线程上执行此操作并触发事件... - Adrian
@Adrian,我已经更新了答案,并提供了一个使用线程的简单示例。 - Chris Taylor
@Chris Taylor,我认为它试图检查MSMQ消息,如果不是的话,你是对的,你有任何参考资料可以看看它是如何工作的吗?提前致谢。 - Saeed Amiri
@Adrian,很高兴。很高兴我能帮到你。 - Chris Taylor
@SaeedAlg,绝对没有涉及到MSMQ。MSMQ甚至不是默认安装的。您可以使用Reflector查看Process.WaitForExit()的实现,其中将为进程句柄创建WaitHandle,并在等待处理程序上调用WaitOne方法。这在本机代码中是非常标准的Win32方法。 - Chris Taylor

1

这是个好主意。请记住,当WaitHandle派生类复制进程句柄时,否则事情会变得非常不可靠,这将需要额外的P/Invoke到kernel32 DuplicateHandle方法。 - Chris Taylor

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