简体   繁体   中英

How to find out if the process is crashed using c++ winapi?

When error occurs in the program, on the screen we can see something like this:

“Windows 资源管理器没有响应”对话框

Is there anyway to determine this situation using c++ winapi? I have aldready tried to use this code to find out if the main thread of the procces is suspend. But it doesn't.
I also tried to send timeot messages(code below) but result is always true, even if error window have appeared.

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 
}

Yes there is a way, all crash interceptors work this way, like the firefox crash reporter.

On windows you can use structured exception handling:

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

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

extract:

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 
}

I found another solution. This error message has it's own procces WerFault.exe , we can simply destroy it with TerminateProcess() and the hang procces will be destroyed too. And then it is quite simple to notice that the required process does not exist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM