如何确定进程是否使用c ++ winapi崩溃?

时间:2016-03-14 19:21:42

标签: c++ winapi

当程序出错时,屏幕上我们可以看到如下内容:

"Windows Explorer is not responding" dialog

无论如何使用c ++ winapi确定这种情况?我已经尝试使用this code来查明procces的主线程是否挂起。但事实并非如此。
我也尝试发送时间消息(下面的代码),但结果始终为真,即使出现了错误窗口。

typedef struct tagENUMINFO
{
// In Parameters
   DWORD PId;

// Out Parameters
   HWND  hWnd;
   HWND  hEmptyWnd;
   HWND  hInvisibleWnd;
   HWND  hEmptyInvisibleWnd;
} ENUMINFO, *PENUMINFO;


BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
   DWORD       pid = 0;
   PENUMINFO   pInfo = (PENUMINFO)lParam;
   TCHAR       szTitle[_MAX_PATH+1];

// sanity checks
   if (pInfo == NULL)
   // stop the enumeration if invalid parameter is given
      return(FALSE);

// get the processid for this window
   if (!::GetWindowThreadProcessId(hWnd, &pid))
   // this should never occur :-)
      return(TRUE);

// compare the process ID with the one given as search parameter
   if (pInfo->PId == pid)
   {
   // look for the visibility first
      if (::IsWindowVisible(hWnd))
      {
      // look for the title next
         if (::GetWindowText(hWnd, szTitle, _MAX_PATH) != 0)
         {
            pInfo->hWnd = hWnd;

         // we have found the right window
            return(FALSE);
         }
         else
            pInfo->hEmptyWnd = hWnd;
      }
      else
      {
      // look for the title next
         if (::GetWindowText(hWnd, szTitle, _MAX_PATH) != 0)
         {
            pInfo->hInvisibleWnd = hWnd;
         }
         else
            pInfo->hEmptyInvisibleWnd = hWnd;
      }
   }

// continue the enumeration
   return(TRUE);
}


HWND GetMainWindow(DWORD PId)
{
   ENUMINFO EnumInfo;

// set the search parameters
   EnumInfo.PId = PId;

// set the return parameters to default values
   EnumInfo.hWnd               = NULL;
   EnumInfo.hEmptyWnd          = NULL;
   EnumInfo.hInvisibleWnd      = NULL;
   EnumInfo.hEmptyInvisibleWnd = NULL;

// do the search among the top level windows
   ::EnumWindows((WNDENUMPROC)EnumWindowsProc, (LPARAM)&EnumInfo);

// return the one found if any
   if (EnumInfo.hWnd != NULL)
      return(EnumInfo.hWnd);
   else if (EnumInfo.hEmptyWnd != NULL)
      return(EnumInfo.hEmptyWnd);
   else if (EnumInfo.hInvisibleWnd != NULL)
      return(EnumInfo.hInvisibleWnd);
   else
      return(EnumInfo.hEmptyInvisibleWnd);
}
DWORD GetProcessByExeName(char *ExeName)
{
    DWORD Pid;

    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    if (Process32First(hProcessSnap, &pe32))
    {
        do
        {
            if (strcmpi(pe32.szExeFile, ExeName) == 0)
            {
                CloseHandle(hProcessSnap);
                return pe32.th32ProcessID;
            }
        } while (Process32Next(hProcessSnap, &pe32));
    }

    CloseHandle(hProcessSnap);
    return 0;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prev, LPSTR cmdline, int show)
{
    HWND Hwnd;
    LRESULT res;
    DWORD PID;
    PID=GetProcessByExeName("procces.exe");
    Hwnd=GetMainWindow(PID);
    res = SendMessageTimeout(Hwnd, WM_NULL, NULL, NULL, SMTO_ABORTIFHUNG, 3000,NULL);
    //res == 1 always 
}

2 个答案:

答案 0 :(得分:0)

是的,有一种方法,所有崩溃拦截器都以这种方式工作,就像firefox崩溃记者一样。

在Windows上,您可以使用结构化异常处理:

参考:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms680657(v=vs.85).aspx

和howto:
http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus

提取:

LONG WINAPI MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionPtrs)
{
  // Do something, for example generate error report
  //..
  // Execute default exception handler next
  return EXCEPTION_EXECUTE_HANDLER; 
} 
void main()
{ 
  SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
  // .. some unsafe code here 
}

答案 1 :(得分:0)

我找到了另一个解决方案。此错误消息具有自己的procces WerFault.exe,我们可以使用TerminateProcess()将其销毁,并且也会销毁挂起过程。然后很容易注意到所需的过程不存在。