[英]How can I know if a process is running?
当我获得对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);
}
这是我在使用反射器后发现的最简单的方法。 我为此创建了一个扩展方法:
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
类是内部的...
同步解决方案:
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.");
}
reshefm 有一个很好的答案; 然而,它没有考虑到进程从未开始的情况。
这是他发布的内容的修改版本。
public static bool IsRunning(this Process process)
{
try {Process.GetProcessById(process.Id);}
catch (InvalidOperationException) { return false; }
catch (ArgumentException){return false;}
return true;
}
我删除了他的 ArgumentNullException ,因为它实际上假设是一个空引用异常,无论如何它都会被系统抛出,我还考虑了进程从未开始或使用 close() 方法关闭的情况过程。
这应该是单行的:
public static class ProcessHelpers {
public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}
这取决于您希望此功能有多可靠。 如果您想知道您拥有的特定流程实例是否仍在运行并以 100% 的准确率可用,那么您就不走运了。 原因是从托管进程对象只有两种方法可以识别进程。
第一个是进程 ID。 不幸的是,进程 ID 不是唯一的,可以回收。 在进程列表中搜索匹配的 ID 只会告诉您有一个具有相同 ID 的进程正在运行,但它不一定是您的进程。
第二项是进程句柄。 尽管它与 Id 存在相同的问题,但使用起来更尴尬。
如果您正在寻找中等级别的可靠性,那么检查具有相同 ID 的进程的当前进程列表就足够了。
Process.GetProcesses()
是要走的路。 但是您可能需要使用一个或多个不同的标准来查找您的进程,这取决于它的运行方式(即作为服务还是作为普通应用程序,无论它是否具有标题栏)。
我尝试了 Coincoin 的解决方案:
在处理某个文件之前,我将其复制为临时文件并打开它。
完成后,如果应用程序仍处于打开状态,我将关闭该应用程序并删除临时文件:
我只是使用一个 Process 变量然后检查它:
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");
}
您也可以使用计时器每次检查过程
也许(可能)我读错了这个问题,但是您是否正在寻找 HasExited 属性,该属性会告诉您 Process 对象表示的进程已退出(正常与否)。
如果您引用的进程有一个 UI,您可以使用 Responding 属性来确定 UI 当前是否正在响应用户输入。
您还可以设置 EnableRaisingEvents 并处理 Exited 事件(异步发送)或如果您想阻止则调用 WaitForExit()。
尽管 .Net 框架支持通过进程 ID 检查现有进程的 API,但这些功能非常慢。 运行 Process.GetProcesses() 或 Process.GetProcessById/Name() 需要大量的 CPU 周期。
通过 ID 检查正在运行的进程的一种更快的方法是使用本机 API OpenProcess() 。 如果返回句柄为 0,则进程不存在。 如果句柄不为 0,则进程正在运行。 由于许可,无法保证此方法始终 100% 有效。
与此相关的问题有很多,因为其他人似乎已经部分解决了:
无论其他人提到的属性是否是内部的,如果允许,您仍然可以通过反射从他们那里获取信息。
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
您可以为Snapshot调用 Win32 代码,也可以使用速度较慢的WMI 。
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
另一种选择是OpenProcess / CloseProcess,但您仍然会遇到与以前相同的异常抛出的相同问题。
对于 WMI - OnNewEvent.Properties["?"]:
您可以为您想要的进程实例化一个 Process 实例,并使用该 .NET Process 对象继续跟踪该进程(它将继续跟踪,直到您显式调用该 .NET 对象上的 Close,即使它正在跟踪的进程已经死亡[这是为了能够给你进程关闭的时间,又名 ExitTime 等])
引用http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
当关联的进程退出时(即,当操作系统通过正常或异常终止将其关闭时),系统存储有关进程的管理信息并返回到调用 WaitForExit 的组件。 然后,Process 组件可以通过使用已退出进程的句柄来访问包括 ExitTime 在内的信息。
由于关联进程已退出,组件的 Handle 属性不再指向现有进程资源。 相反,句柄只能用于访问操作系统关于进程资源的信息。 系统知道 Process 组件尚未释放的已退出进程的句柄,因此它会将 ExitTime 和 Handle 信息保留在内存中,直到 Process 组件专门释放资源。 因此,任何时候为 Process 实例调用 Start 时,在关联进程终止并且不再需要有关它的任何管理信息时调用 Close。 Close 释放分配给退出进程的内存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.