-2

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

"Windows Explorer is not responding" dialog

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 
}
Community
  • 1
  • 1
Kirill
  • 11
  • 4
  • Please include content directly rather than links to it. – kfsone Mar 14 '16 at 19:24
  • I'd like to do this way But I have just reg and haven't got 10 reputation to post images directly. – Kirill Mar 14 '16 at 19:30
  • I was actually speaking more to your link to "this code". – kfsone Mar 14 '16 at 19:32
  • 1
    That dialog only occurs when a process hangs, not if it crashes. It means the process is running (so from the kernel's point of view everything is normal) but is not processing window messages. I suppose you could send a window message to the process and see whether you get a response. – Harry Johnston Mar 14 '16 at 20:52
  • Use [`SendMessageTimeout()`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms644952.aspx), using its `uTimeout` parameter and `SMTO_ABORTIFHUNG` flag, to send a `WM_NULL` message to the target window. – Remy Lebeau Mar 15 '16 at 03:21
  • I've tried this, but it returns 1 even after hang. I posted code in the qustion. – Kirill Mar 15 '16 at 19:11
  • If you want to debug more, use Application Verifier – v.oddou Mar 16 '16 at 02:55

2 Answers2

0

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 
}
v.oddou
  • 6,476
  • 3
  • 32
  • 63
0

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.

Kirill
  • 11
  • 4
  • I believe the WerFault is invoked in case of crash (Windows equivalent of the core dump), the process is halted but remains zombie as long as the exit structures handles have live references, or something like that. – v.oddou Mar 17 '16 at 01:02