如何判断一个进程是否在运行?

194

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

14个回答

0
你可以为想要的进程实例化一个 Process 实例,并使用该 .NET Process 对象不断跟踪该进程(即使被跟踪的进程已经死亡,只要您明确调用了该 .NET 对象上的 Close 方法,它就会继续跟踪 [这是为了能够给您进程关闭的时间,例如 ExitTime 等])。
引用 http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx
当相关进程退出时(也就是通过正常或异常终止被操作系统关闭时),系统会存储有关该进程的管理信息,并返回给调用 WaitForExit 的组件。然后,Process 组件可以使用已退出进程的 Handle 访问包括 ExitTime 在内的信息。
由于相关进程已经退出,组件的 Handle 属性不再指向现有的进程资源。相反,该句柄仅可用于访问操作系统关于该进程资源的信息。系统知道尚未被 Process 组件释放的已退出进程的句柄,因此它将 ExitTime 和 Handle 信息保存在内存中,直到 Process 组件特别释放资源。因此,每次为 Process 实例调用 Start 时,当相关进程已经终止且您不再需要任何管理信息时,请调用 Close。Close 释放为已退出进程分配的内存。

0

尽管 .Net 框架支持通过进程 ID 检查现有进程的 API,但这些函数非常慢。运行 Process.GetProcesses() 或 Process.GetProcessById/Name() 需要大量的 CPU 循环。

检查正在运行的进程 ID 的更快方法是使用本地 API OpenProcess()。如果返回的句柄为 0,则该进程不存在。如果句柄不为 0,则该进程正在运行。由于权限问题,无法保证此方法始终能够 100% 正常工作。


如果每次打开一个新窗口就调用 GetProcessById 函数,会有多慢? - demberto
提供GetProcessByName等函数速度较慢的数量级可能会有所帮助。在BenchmarkDotNet中,GetProcessByName在我的机器上(.NET 7)花费了5毫秒。 - Andrew D. Bond

0

我尝试了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 );

目前为止它可以工作


3
openApplication.HasExited()中,HasExited不是一个函数。正确的方式应该是openApplication.HasExited - caiosm1005

0
安全查询所有活动进程的名称列表。 如果您正在寻找所有未终止的活动进程或仅仅是远程进程的痕迹,那么请尝试这个安全查询,不会出现任何失败,就像没有异常一样...无论如何,您都会得到结果,而且不会失败... 如果该方法返回“true”,则列表将包含所有搜索到的进程,否则返回“false”和一个空列表,如果列表为null,则表示名称参数设置不正确,没有进行搜索...
    /// <summary>
    /// Safe Try...
    /// </summary>
    /// <param name="processName"></param>
    /// <param name="processList"></param>
    /// <returns></returns>
    public static bool ProcessIsAnyRunning(this string processName, out List<Process> processList)
    {
        processList = null;
        var ret = !string.IsNullOrWhiteSpace(processName);
        if (ret)
        {
            var processArr = Process.GetProcessesByName(processName);
            ret = processArr.Length > 0;
            if (ret) 
            {
                processList = new List<Process>();
                foreach (var process in processArr)
                    try
                    {
                        process.Refresh();
                        if (process.HasExited)
                            process.Dispose();
                        else
                            processList.Add(process);
                    }
                    catch
                    {
                        continue;
                    }
                ret = processList.Count > 0;
            }
        }
        return ret;
    }

感谢您对Stack Overflow社区做出贡献的兴趣。这个问题已经有了相当多的答案,其中一个答案已经得到社区的广泛验证。您确定您的方法之前没有被提出过吗?如果是这样的话,解释一下您的方法与众不同的地方,以及在什么情况下您的方法可能更好,或者为什么您认为之前的答案不够满意,这将非常有帮助。您能否友好地编辑您的答案并提供解释? - undefined
这是一个安全的请求,没有崩溃,就像没有异常的尝试一样...无论如何,您都会得到结果,而且不会放弃... - undefined
很有用。你能把你的回答修改一下,包括这个吗? - undefined

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