我怎么知道进程是否正在运行?

时间:2008-11-04 16:13:09

标签: c# .net process

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

13 个答案:

答案 0 :(得分:220)

这是一种使用名称:

的方法
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);
}

答案 1 :(得分:24)

这是我在使用反射器后找到的最简单的方法。 我为此创建了一个扩展方法:

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类是内部的......

答案 2 :(得分:16)

同步解决方案:

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.");
}

答案 3 :(得分:8)

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()方法的情况关闭这个过程。

答案 4 :(得分:6)

这应该是一个单行:

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

答案 5 :(得分:3)

这取决于您希望此功能的可靠性。如果您想知道您所拥有的特定流程实例是否仍在运行并且可以100%准确地获得,那么您运气不好。原因是托管流程对象只有两种方法来识别流程。

第一个是流程ID。不幸的是,流程ID并不是唯一的,可以回收利用。在流程列表中搜索匹配的ID只会告诉您正在运行具有相同ID的流程,但它不一定是您的流程。

第二项是流程处理。它与Id有相同的问题,而且使用起来更尴尬。

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

答案 6 :(得分:1)

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

答案 7 :(得分:0)

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

如果您引用的进程具有UI,则可以使用Responding属性来确定UI当前是否正在响应用户输入。

您还可以设置EnableRaisingEvents并处理Exited事件(以异步方式发送)或调用WaitForExit()(如果要阻止)。

答案 8 :(得分:0)

您可以为您想要的进程实例化一次Process实例,并继续使用该.NET Process对象跟踪进程(它将继续跟踪,直到您明确地在该.NET对象上调用Close,即使它是跟踪已经死了[这是为了能够给你时间关闭,也就是退出时间等。]

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

  

当关联的进程退出时(也就是当它被关闭时)   操作系统通过正常或异常终止),系统   存储有关流程的管理信息并返回到   已调用WaitForExit的组件。然后,Process组件可以   通过使用,访问包括ExitTime的信息   处理退出的流程。

     

因为关联的进程已退出,所以Handle属性   组件不再指向现有的流程资源。代替,   句柄只能用于访问操作系统   有关流程资源的信息。系统知道句柄   退出Process组件尚未发布的进程,   所以它将ExitTime和Handle信息保存在内存中,直到   流程组件专门释放资源。为此原因,   任何时候为Process实例调用Start,在调用时调用Close   相关流程已终止,您不再需要任何流程   关于它的行政信息。关闭释放分配的内存   退出过程。

答案 9 :(得分:0)

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

它有效(到目前为止)

答案 10 :(得分:0)

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

您也可以使用计时器每次检查过程

答案 11 :(得分:0)

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

通过ID检查正在运行的进程的一种更快的方法是使用本机API OpenProcess()。如果return handle为0,则该进程不存在。如果handle不同于0,则进程正在运行。由于许可,无法保证此方法始终100%有效。

答案 12 :(得分:0)

与此相关的问题很多,而其他一些问题似乎可以部分解决:

  • 不保证任何实例成员都是线程安全的。这意味着在尝试评估对象的属性时,快照的生存期可能会出现竞争条件。
  • 在不允许访问该属性和其他此类属性的权限的情况下,进程句柄将为WinCCException抛出ACCESS DENIED。
  • 对于“ IS N'T RUNNING”状态,尝试评估其某些属性时也会引发ArgumentException。

其他人提到的属性是否是内部的,如果允许的话,您仍然可以通过反射从这些属性中获取信息。

var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);

您可以为Snapshot设置Win32代码,也可以使用速度较慢的WMI

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

另一个选择是OpenProcess / CloseProcess,但是您仍然会遇到相同的问题,但抛出的异常与以前相同。

对于WMI-OnNewEvent.Properties [“?”]:

  • “ ParentProcessID”
  • “ ProcessID”
  • “ ProcessName”
  • “ SECURITY_DESCRIPTOR”
  • “会话ID”
  • “ Sid”
  • “ TIME_CREATED”