【问题标题】:How to track a process如何跟踪流程
【发布时间】:2014-11-07 08:16:08
【问题描述】:

问题是如何跟踪我从应用程序启动的进程。

我正在做一个“启动器”,我想跟踪我启动的程序何时关闭。

我检查了这些链接,但我认为这与我尝试的不完全相同,因为我将启动的进程都是javaw.exe,我需要单独对待它们。

.Net Process monitor

How to detect a process start & end using c# in windows?

这就是代码现在的样子:

{
    Process proc = new Process();
    proc.Exited += EclipseInstanceClosed;
    proc.Disposed += EclipseInstanceDisposed;
    // this property is a *.exe path: 'C:\eclipse\eclipseV4.4.1\eclipse.exe' for example
    proc.StartInfo.FileName = SelectedEclipseInstance.Exec;
    proc.StartInfo.UseShellExecute = true;

    proc.Start();
}

...

void EclipseInstanceClosed(object sender, EventArgs e)
{
    MessageBox.Show("Eclipse was closed!");
}

void EclipseInstanceDisposed(object sender, EventArgs e)
{
    MessageBox.Show("Eclipse was disposed!");
}

但是当我关闭程序时不会引发这些事件。

有什么想法吗?

更新:

我也用proc.EnableRaisingEvents = true; 尝试了这个解决方案(why Process's Exited method not being called?),但没有成功

更新二:

我修改了代码,以便在任务中启动该过程。在这种情况下,会引发事件。是什么原因?

LaunchEclipseProcess();

...

private async void LaunchEclipseProcess()
{
    await Task.Run(() =>
    {
        Process proc = new Process();
        proc.EnableRaisingEvents = true;
        proc.StartInfo.UseShellExecute = true;

        proc.Exited += EclipseInstanceClosed;
        proc.Disposed += EclipseInstanceDisposed;

        proc.StartInfo.FileName = SelectedEclipseInstance.Exec;

        proc.Start();
    });
}

【问题讨论】:

  • 您是否保留了对您创建的proc 对象的引用?
  • 没有。该对象是在双击事件中创建的。
  • 我认为问题在于当您退出您提到的代码块时,您对proc 的引用松散了,并且它被垃圾收集了。尝试从您的块中定义您的 proc 并检查结果

标签: c# process monitor


【解决方案1】:
proc.Exited += EclipseInstanceClosed;

请注意,当启动的应用程序关闭时,上述代码不会通知。 process.Exited 事件用于了解关联进程何时完成(您通过调用 Process.Start() 触发的进程)。但是,如果您想检查启动的应用程序是否正在运行/关闭,您可以在 EclipseInstanceClosed 事件中编写如下监控代码。

void EclipseInstanceClosed(object sender, EventArgs e)
{
  while (true)
  {
     Process runningEclipseProcess = Process.GetProcessesByName("ExclipeProcessName").FirstOrDefault();

     if (runningEclipseProcess != null)
     {
        //Exclipe is not closed. Wait for 1 sec and check again.
        Thread.Sleep(1000);
     }
     else
     {
        //Exclipe is closed. Notify the user
        MessageBox.Show("Eclipse was closed!");
        break;
    }
  }     
}

【讨论】:

  • 如果您有多个具有相同进程名称的相同应用程序实例,这将不起作用。
  • @HamidP 同意。只要 OP 没有这种情况应该没问题。
  • 正如我所说,所有进程都是“javaw.exe”,而且我无法通过 processName 单独识别,因为如果我运行同一 exec 的不同实例,它们共享相同的名称。
  • 你可以监控它。在启动实例之前拍摄所有正在运行的 javaw.exe 的快照。保留这些信息(Process.Id)。然后,一旦您启动了一个新实例,就拍摄一个新快照。最新的 javaw.exe 将有一个 Process.Id,您在刚刚保留的列表中没有。然后,您可以通过您使用最初创建的代码获取的 Process.Id 监控这些新流程中的每一个(proc = Process.GetProcessById(id)。
【解决方案2】:

你试过了吗

proc.WaitForExit()

如果您需要其余代码继续执行并在完成后运行 EclipseInstanceClosed 方法,您甚至可以在另一个线程上运行 proc.WaitForExit()。

如果进程实际上已停止,则此方法将返回。如果它永远不会返回,则意味着该过程从未停止过。然后你需要排查为什么它不停止。


在启动您的应用的第一个实例之前,获取所有正在运行的 Javaw.exe 及其 PID 的列表。保留这份清单。 启动应用程序的新实例后,请重新检查 javaw.exe 列表。找到新的。创建一个对此过程的“引用”以监控它,就像您在上面编写代码一样。

var proc = Process.GetProcessById(id);

继续监控并做你的事情。

如果您启动一个新进程,请重做上述逻辑。列出所有 javaw.exe 之前和之后的所有内容,以便让您的 Process.Id 进行监控。

如果每个 javaw.exe 都使用参数运行,如果上述方法不够好,还有一些方法可以获取这些参数以缩小目标进程。

【讨论】:

  • process.WaitForExit() 只能用于跟踪启动进程是否已完成/退出。但是 OP 正在启动一个 eclipse 应用程序,他想知道这个启动的应用程序何时关闭。
  • 啊。我不熟悉 Eclipse 如何运行其运行进程。我假设它是一个运行多个“应用程序”的长寿过程。如果应用程序关闭时 eclipse 没有关闭,那么上面的代码将根本不起作用。该代码用于关闭进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 2021-12-20
  • 1970-01-01
相关资源
最近更新 更多