我怎么知道一个进程是否正在运行?
当我得到一个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); }
这是使用reflection镜后find的最简单的方法。 我为此创build了一个扩展方法:
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
类是内部的…
同步解决scheme:
void DisplayProcessStatus(Process process) { process.Refresh(); // Important if(process.HasExited) { Console.WriteLine("Exited."); } else { Console.WriteLine("Running."); } }
asynchronous解决scheme:
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."); }
reshefm有一个相当不错的答案; 然而,这并没有说明这个过程从未开始的情况。
这里是他发布的一个修改版本。
public static bool IsRunning(this Process process) { try {Process.GetProcessById(process.Id);} catch (InvalidOperationException) { return false; } catch (ArgumentException){return false;} return true; }
我删除了他的ArgumentNullException,因为它实际上假设是一个空引用exception,它被系统抛出,我也说明了这个过程从未开始的情况,或者close()方法被用来closures处理。
这应该是一个单行的:
public static class ProcessHelpers { public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0; }
这取决于你想要这个function的可靠性。 如果您想知道您所拥有的特定stream程实例是否仍在运行并且100%准确无误,那么您运气不佳。 原因在于,从被pipe理的过程对象中,只有两种方法可以识别过程。
第一个是进程ID。 不幸的是,进程ID不是唯一的,可以回收。 在进程列表中search一个匹配的Id只会告诉你有一个运行相同ID的进程,但不一定是你的进程。
第二个项目是进程句柄。 它有同样的问题,虽然作为Id,它是更尴尬的工作。
如果您正在寻找中等可靠性,那么检查当前进程列表是否具有相同ID的进程就足够了。
Process.GetProcesses()
是要走的路。 但是,您可能需要使用一个或多个不同的标准来查找您的stream程,具体取决于它的运行方式(即作为服务或普通应用程序,无论标题栏是否有标题栏)。
也许(可能)我错误地阅读了这个问题,但是你在寻找HasExited属性,它会告诉你Process对象表示的进程已经退出(正常或不正常)。
如果你有一个引用的过程有一个用户界面,你可以使用响应属性来确定用户界面当前是否响应用户input。
您还可以设置EnableRaisingEvents并处理Exited事件(它是asynchronous发送的),或者如果您想阻塞,请调用WaitForExit()。
你可以为你想要的进程实例化一个Process实例,并使用该.NET进程对象跟踪进程(它将继续跟踪,直到你明确地调用了.NET对象的Close,即使它正在跟踪的进程已经死了[这是为了能够给你closures进程的时间,又名ExitTime等])
引用http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
当一个关联的进程退出时(也就是说,当操作系统通过正常或exception终止closures时),系统存储有关进程的pipe理信息并返回到已调用WaitForExit的组件。 然后Process组件可以通过使用Handle到退出的进程来访问包含ExitTime的信息。
由于关联的进程已退出,组件的Handle属性不再指向现有的进程资源。 相反,该句柄只能用于访问操作系统有关进程资源的信息。 系统知道进程组件尚未释放的已退出进程的句柄,因此它将ExitTime和Handle信息保留在内存中,直到进程组件专门释放资源为止。 由于这个原因,每当你调用一个Process实例的Start时,当关联进程已经终止,并且不再需要关于它的任何pipe理信息时,调用Close。 closures释放分配给退出进程的内存。
我尝试了Coincoin的解决scheme:
在处理一些文件之前,我将它作为临时文件复制并打开。
完成后,如果应用程序仍处于打开状态,则closures该应用程序并删除临时文件:
我只是使用一个Processvariables,然后检查它:
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 ); }
稍后closures应用程序:
... 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"); }
你也可以使用一个定时器来检查每一个进程
尽pipe.NET框架支持通过进程ID检查现有进程的API,但这些function非常缓慢。 运行Process.GetProcesses()或Process.GetProcessById / Name()会花费大量的CPU周期。
通过ID检查正在运行的进程的更快速的方法是使用本地API OpenProcess() 。 如果返回句柄为0,则进程不存在。 如果句柄不是0,则进程正在运行。 不能保证这个方法在任何时候都会因为许可而全部工作。