检测进程是不是仍在运行

Posted

技术标签:

【中文标题】检测进程是不是仍在运行【英文标题】:Detecting if a process is still running检测进程是否仍在运行 【发布时间】:2009-08-06 11:45:53 【问题描述】:

我需要检查具有给定 HANDLE 的进程是否仍在运行,我尝试使用以下代码执行此操作,但它总是在第二次返回 false 时返回,即使进程正在运行。

bool isProcessRunning(HANDLE process)

    if(process == INVALID_HANDLE_VALUE)return false;

    DWORD exitCode;
    if(GetExitCodeProcess(process, &exitCode) != 0)
        return false;//always returns here

    return GetLastError() == STILL_ACTIVE;//still running

【问题讨论】:

【参考方案1】:

您可以通过使用来测试过程寿命

bool isProcessRunning(HANDLE process)

   return WaitForSingleObject( process, 0 ) == WAIT_TIMEOUT;

【讨论】:

只需要添加对 INVALID_HANDLE_VALUE 的检查,因为它报告进程正在运行,但它甚至无效:) 如果您打开了进程句柄,即使它已终止,WaitForSingleObject 之类的 API 也不应该返回 INVALID_HANDLE_VALUE。句柄和基础对象必须保持打开状态,直到被引用进程显式关闭(或这些进程被终止)。你确定你不是试图在进程 ID 而不是句柄上调用它吗? 我的意思是在 WaitForSingleObject 之前进行检查,以防进程尚未创建,因此句柄仍处于我将其初始化为的值,即 INVALID_HANDLE_VALUE,因为始终将 INVALID_HANDLE_VALUE 传递给 WaitForSingleObject超时(即 INVALID_HANDLE_VALUE 似乎从未处于信号状态)。【参考方案2】:

http://msdn.microsoft.com/en-us/library/ms683189%28VS.85%29.aspx

返回值

如果函数成功,则返回 值非零。

如果函数 失败,返回值为零。到 获取扩展错误信息,调用 GetLastError.

【讨论】:

这不是答案。【参考方案3】:

我知道这有点晚了,但是如果您想要获得预期的结果,您的代码应该是这样的。

bool isProcessRunning(HANDLE process)
    
    DWORD exitCodeOut;

    // GetExitCodeProcess returns zero on failure
    if( GetExitCodeProcess( process, &exitCodeOut ) == 0 )
    
        // Optionally get the error
        // DWORD error = GetLastError();
        return false;
    
    // Return if the process is still active
    return exitCodeOut == STILL_ACTIVE;

如果您只有进程 ID (PID),此 sn-p 将起作用(无错误检查):

bool isProcessRunning(DWORD processID)
    
    if( HANDLE process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processID ) )
    
        DWORD exitCodeOut;
        // GetExitCodeProcess returns zero on failure
        if( GetExitCodeProcess( process, &exitCodeOut ) != 0 )
        
            // Return if the process is still active
            return exitCodeOut == STILL_ACTIVE;
        
    
    return false;

【讨论】:

应该避免这种方法,因为可能会为已退出的进程获取 STILL_ACTIVE。 (这是一个有效的退出代码。) @HarryJohnston 当且仅当进程使用 259 作为退出代码,对吗? Microsoft 建议不要将其用作错误代码。由于我正在检查的过程没有机会返回 259(正如我所写的那样),因此退出代码的使用是完全可以接受的。这似乎是一个妖怪,仅当您检查您无权控制的进程的退出代码时才适用。 (不过,了解并意识到这一点是件好事) 在那种特定情况下,这种方法可能是可以接受的。但是,OP 没有说明他们正在检查的过程是否是他们自己的代码,而且您的回答也没有说明这是一项要求。 ... 就个人而言,考虑到使用 WaitForSingleObject 是多么容易,我只是看不到使用 GetExitCodeProcess 的任何优势。当您可以通过使用 WaitForSingleObject 以简单的方式消除风险时,或者通过检查子程序的每个可能的退出路径(包括您可能正在使用的任何第三方库)来以困难的方式消除风险,那么,为什么要采用艰难的方式呢? :-) 刚刚尝试使用WaitForSingleObject,即使进程仍在运行,它也会返回WAIT_TIMEOUT,可能是因为我们正在使用QSharedMemory,它锁定了进程接收事件(它已经在等待,基本上) .因此,在我们的特定用例中无法使用WaitForSingleObject(p, 0)。有好处:-) 我最初实现该功能时可能遇到过这个问题,但忘记了为什么选择GetExitCodeProcess 的细节。总而言之,这是一个有用的练习,希望它对未来的人有所帮助。【参考方案4】:

您可以使用EnumProcesses() 让所有进程在 Windows 上运行。 比如:

bool IsProcessRunning(int pid)  
  
unsigned long processes[2048];  
unsigned long num_proc = 0;  
unsigned long needed = 0;  

  // assume that 2048 processes are enought  
  if (EnumProcesses(processes, sizeof(processes), &needed))  
   num_proc = needed / sizeof(DWORD);  

  for (int i = 0; i < num_proc; i++)  
    if (processes[i] == pid)  
      return true;  

   return false;  

【讨论】:

@gimpf 不管它有多复杂,它仍然可能有用。 虽然效率很低,而且由于它使用进程 ID 而不是句柄,因此受制于固有的竞争条件。 可能有用,我猜,但可能只在边缘情况下。

以上是关于检测进程是不是仍在运行的主要内容,如果未能解决你的问题,请参考以下文章

Process.Responding检测进程退出,同时进程运行

vb 检测某个进程是不是运行

检测您的网站是不是在后台运行

如何检测一个进程是不是已经执行完毕

如何通过BAT来实现检测程序是不是在运行

检测进程是不是由 IE 在保护模式下启动