如何知道某个进程是否正在运行?

问题描述:

当我得到System.Diagnostics.Process的引用时,如何知道某个进程当前是否正在运行?如何知道某个进程是否正在运行?

这是一种名为做到这一点:

Process[] pname = Process.GetProcessesByName("notepad"); 
if (pname.Length == 0) 
    MessageBox.Show("nothing"); 
else 
    MessageBox.Show("run"); 

你也可以遍历所有的过程,获得后面操纵ID:

Process[] processlist = Process.GetProcesses(); 
foreach(Process theprocess in processlist){ 
    Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id); 
} 
+0

这正是我一直在寻找的。即使这是一个非常古老的帖子,你会向我解释这是如何有效的C#。我不怀疑它,我认为它有效,但我从来没有见过没有{}。 – MatthewD 2015-11-18 19:06:12

+2

@MatthewD:C#`只有一行的if/else`语句不需要用花括号来表示块语句。这也适用于“foreach”和“for”语句。它归结为编码风格。 – Hallmanac 2015-11-24 01:36:28

+0

我也对此进行了一些研究,发现信息,但我没有看到“for”信息。多年的c#.net开发者和我从未见过这种风格。就像他们说的,“你每天都会学到新的东西”。谢谢你的帖子和回复.. – MatthewD 2015-11-25 03:06:47

Process.GetProcesses()是要走的路。但是,您可能需要使用一个或多个不同的标准来查找您的流程,具体取决于它的运行方式(即作为服务或普通应用程序,不管它是否具有标题栏)。

+0

如果您将此方法放在一个循环中,则会花费大量的CPU周期。我建议使用GetProcessByName()或GetProcessByID()。 – 2016-07-08 16:55:34

这取决于你想要这个功能的可靠程度。如果您想知道您拥有的特定流程实例是否仍在运行并且100%准确可用,那么您的运气不好。原因在于,从被管理的过程对象中,只有两种方法可以识别过程。

第一个是进程ID。不幸的是,进程id不是唯一的,可以回收。在进程列表中搜索匹配的Id只会告诉你有一个进程使用相同的ID运行,但它不一定是你的进程。

第二项是过程句柄。它与Id一样存在相同的问题,并且与其合作更加尴尬。

如果您正在寻找中等级别的可靠性,那么检查当前进程列表以找到具有相同ID的进程就足够了。

也许(可能)我错误地阅读了这个问题,但是您是否在寻找HasExited属性,它会告诉您Process对象所代表的进程已经退出(通常与否)。

如果你的程序中有一个参考,以具有UI可以使用响应属性来确定UI目前正对用户输入或没有。

您还可以设置EnableRaisingEvents并处理Exited事件(它是异步发送的),或者如果您想阻塞,请调用WaitForExit()。

同步溶液:

void DisplayProcessStatus(Process process) 
{ 
    process.Refresh(); // Important 


    if(process.HasExited) 
    { 
     Console.WriteLine("Exited."); 
    } 
    else 
    { 
     Console.WriteLine("Running."); 
    } 
} 

异步溶液:

void RegisterProcessExit(Process process) 
{ 
    // NOTE there will be a race condition with the caller here 
    // how to fix it is left as an exercise 
    process.Exited += process_Exited; 
} 

static void process_Exited(object sender, EventArgs e) 
{ 
    Console.WriteLine("Process has exited."); 
} 
+5

对于第一个选项:我怎么知道这个过程是否是从第一个地方开始的? – reshefm 2008-11-06 11:39:31

这是我使用反射后发现的最简单的方法。 我创建该扩展方法:

public static class ProcessExtensions 
{ 
    public static bool IsRunning(this Process process) 
    { 
     if (process == null) 
      throw new ArgumentNullException("process"); 

     try 
     { 
      Process.GetProcessById(process.Id); 
     } 
     catch (ArgumentException) 
     { 
      return false; 
     } 
     return true; 
    } 
} 

Process.GetProcessById(processId)方法调用ProcessManager.IsProcessRunning(processId)方法和在情况下的处理不存在引发ArgumentException。由于某种原因,ProcessManager类是内部的...

+0

这是一个非常好的答案;但是,您不应该通过参数null异常(因为无论如何都会抛出null引用异常,并且您没有对异常执行任何操作。而且,如果您没有调用Start(),则会得到InvalidOperationException,或者你调用了close()方法,我发布了另一个应答来解决这两种情况 – Aelphaeis 2014-01-31 14:52:48

您可以为您想要的进程实例化一次Process实例,并使用该.NET进程对象跟踪进程(它会一直跟踪,直到您调用Close该.NET对象显式地,即使它正在跟踪的进程已经死了[这是为了能够给你关闭进程的时间,也就是ExitTime等。])

引用http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx

当相关联的处理退出(即,当通过正常或异常终止关闭由 操作系统),该系统对 存储管理信息处理并返回到已调用WaitForExit的组件 。过程组件然后可以通过使用 句柄来访问包含ExitTime的信息, Handle到退出的进程。

由于关联进程已退出,因此 组件的Handle属性不再指向现有的进程资源。相反, 句柄只能用于访问有关进程资源的操作系统的 信息。系统知道处理 已退出进程组件, 尚未释放的进程,因此它会将ExitTime和Handle信息保留在内存中,直到 进程组件专门释放资源为止。由于这个原因,当您调用Process实例的任何时候,您都可以拨打 ,当 关联进程已终止,并且不再需要关于它的任何 管理信息时,请调用Close。关闭将分配给内存 的内存释放到退出的进程。

我试图Coincoin的解决方案:
处理一些文件之前,我复制它作为一个临时文件并打开它。
当我完成后,我关闭应用程序,如果它仍处于打开状态,并删除 临时文件:
我只是用一个过程变量和事后检查:

private Process openApplication; 
private void btnOpenFile_Click(object sender, EventArgs e) { 
    ... 
    // copy current file to fileCache 
    ... 
    // open fileCache with proper application 
    openApplication = System.Diagnostics.Process.Start(fileCache); 
} 

后来我关闭应用程序:

... 
openApplication.Refresh(); 

// close application if it is still open  
if (!openApplication.HasExited()) { 
    openApplication.Kill(); 
} 

// delete temporary file 
System.IO.File.Delete(fileCache); 

它的工作原理(到目前为止)

string process="notepad"; 
    if (Process.GetProcessesByName(process).Length == 0) 
    { 
    MessageBox.Show("Working"); 
    } 
    else 
    { 
    MessageBox.Show("Not Working"); 
    } 

人所以你可以使用一个定时器来检查每个进程

reshefm有一个相当不错的答案;然而,这并没有说明这个过程从未开始的情况。

这是他发布的内容的修改版本。

public static bool IsRunning(this Process process) 
    { 
     try {Process.GetProcessById(process.Id);} 
     catch (InvalidOperationException) { return false; } 
     catch (ArgumentException){return false;} 
     return true; 
    } 

我脱下ArgumentNullException,因为它实际上是想要一个空引用异常,它就会被系统反正扔,我也占了其中的过程是从来没有开始,开始的形势或接近( )方法被用来关闭该过程。

这应该是一个班轮:

public static class ProcessHelpers { 
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0; 
} 

尽管通过有关进程ID检查现有流程的.Net框架支持的API,这些功能都非常慢。运行Process.GetProcesses()或Process.GetProcessById/Name()会花费大量的CPU周期。

通过ID检查正在运行的进程的更快速的方法是使用本地API OpenProcess()。如果返回句柄为0,则该过程不存在。如果句柄不是0,则进程正在运行。无法保证此方法在许可的情况下始终可以100%正常工作。