<p>What's the best way to detect an application crash in XP (produces the same pair of 'error' windows each time - each with same window title) and then restart it?</p>

<p>I'm especially interested to hear of solutions that use minimal system resources as the system in question is quite old. </p>

<p>I had thought of using a scripting language like AutoIt (<a href="http://www.autoitscript.com/autoit3/" rel="noreferrer">http://www.autoitscript.com/autoit3/</a>), and perhaps triggering a 'detector' script every few minutes? </p>

<p>Would this be better done in Python, Perl, PowerShell or something else entirely?</p>

<p>Any ideas, tips, or thoughts much appreciated.</p>

<p>EDIT: It doesn't actually crash (i.e. exit/terminate - thanks @tialaramex). It displays a dialog waiting for user input, followed by another dialog waiting for further user input, then it actually exits. It's these dialogs that I'd like to detect and deal with.</p>

[{'answer_id': 78095, 'author': 'Vinko Vrsalovic', 'author_id': 5190, 'author_profile': 'https://Stackoverflow.com/users/5190', 'pm_score': 3, 'selected': True, 'text': '<p>How about creating a wrapper application that launches the faulty app as a child and waits for it? If the exit code of the child indicates an error, then restart it, else exit.</p>\n'}, {'answer_id': 78242, 'author': 'Jorge Córdoba', 'author_id': 2695, 'author_profile': 'https://Stackoverflow.com/users/2695', 'pm_score': 4, 'selected': False, 'text': '<p>Best way is to use a named <a href="http://msdn.microsoft.com/en-us/library/ms684266(VS.85).aspx" rel="noreferrer">mutex</a>.</p>\n\n<ol>\n<li>Start your application.</li>\n<li>Create a new named mutex and take ownership over it</li>\n<li>Start a new process (process not thread) or a new application, what you preffer.</li>\n<li>From that process / application try to aquire the mutex. The process will block</li>\n<li>When application finish release the mutex (signal it)</li>\n<li>The "control" process will only aquire the mutex if either the application finishes or the application crashes.</li>\n<li>Test the resulting state after aquiring the mutex. If the application had crashed it will be WAIT_ABANDONED</li>\n</ol>\n\n<p><strong>Explanation:</strong> When a thread finishes without releasing the mutex any other process waiting for it can aquire it but it will obtain a WAIT_ABANDONED as return value, meaning the mutex is abandoned and therfore the state of the section it was protected can be unsafe.</p>\n\n<p>This way your second app won\'t consume any CPU cycles as it will keep waiting for the mutex (and that\'s enterely handled by the operating system)</p>\n'}, {'answer_id': 86066, 'author': 'Eclipse', 'author_id': 8701, 'author_profile': 'https://Stackoverflow.com/users/8701', 'pm_score': 2, 'selected': False, 'text': '<p>I realize that you\'re dealing with Windows XP, but for people in a similar situation under Vista, there are new <a href="http://msdn.microsoft.com/en-us/library/aa373347.aspx" rel="nofollow noreferrer">crash recovery API</a>s available.  <a href="http://community.bartdesmet.net/blogs/bart/archive/2006/11/11/Windows-Vista-Application-Recovery-with-C_2300_.aspx" rel="nofollow noreferrer">Here\'s a good introduction</a> to what they can do. </p>\n'}, {'answer_id': 783527, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': "<p>I think the main problem is that Dr. Watson displays a dialog\nand keeps your process alive. </p>\n\n<p>You can write your own debugger using the Windows API and\nrun the crashing application from there. \nThis will prevent other debuggers from catching the crash of\nyour application and you could also catch the Exception event.</p>\n\n<p>Since I have not found any sample code, I have written this\nPython quick-and-dirty sample. I am not sure how robust it is\nespecially the declaration of DEBUG_EVENT could be improved.</p>\n\n<pre><code>from ctypes import windll, c_int, Structure\nimport subprocess\n\nWaitForDebugEvent = windll.kernel32.WaitForDebugEvent    \nContinueDebugEvent = windll.kernel32.ContinueDebugEvent\nDBG_CONTINUE = 0x00010002L    \nDBG_EXCEPTION_NOT_HANDLED = 0x80010001L\n\nevent_names = {    \n    3: 'CREATE_PROCESS_DEBUG_EVENT',\n    2: 'CREATE_THREAD_DEBUG_EVENT',\n    1: 'EXCEPTION_DEBUG_EVENT',\n    5: 'EXIT_PROCESS_DEBUG_EVENT',\n    4: 'EXIT_THREAD_DEBUG_EVENT',\n    6: 'LOAD_DLL_DEBUG_EVENT',\n    8: 'OUTPUT_DEBUG_STRING_EVENT', \n    9: 'RIP_EVENT',\n    7: 'UNLOAD_DLL_DEBUG_EVENT',\n}\nclass DEBUG_EVENT(Structure):\n    _fields_ = [\n        ('dwDebugEventCode', c_int),\n        ('dwProcessId', c_int),\n        ('dwThreadId', c_int),\n        ('u', c_int*20)]\n\ndef run_with_debugger(args):\n    proc = subprocess.Popen(args, creationflags=1)\n    event = DEBUG_EVENT()\n\n    while True:\n        if WaitForDebugEvent(pointer(event), 10):\n            print event_names.get(event.dwDebugEventCode, \n                    'Unknown Event %s' % event.dwDebugEventCode)\n            ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)\n        retcode = proc.poll()\n        if retcode is not None:\n            return retcode\n\nrun_with_debugger(['python', 'crash.py'])\n</code></pre>\n"}, {'answer_id': 949667, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>Here is a slightly improved version.</p>\n\n<p>In my test the previous code run in an infinite loop when the faulty exe generated an "access violation".</p>\n\n<p>I\'m not totally satisfied by my solution because I have no clear criteria to know which exception should be continued and which one couldn\'t be (The ExceptionFlags is of no help).</p>\n\n<p>But it works on the example I run.</p>\n\n<p>Hope it helps,\nVivian De Smedt</p>\n\n<pre><code>from ctypes import windll, c_uint, c_void_p, Structure, Union, pointer\nimport subprocess\n\nWaitForDebugEvent = windll.kernel32.WaitForDebugEvent\nContinueDebugEvent = windll.kernel32.ContinueDebugEvent\nDBG_CONTINUE = 0x00010002L\nDBG_EXCEPTION_NOT_HANDLED = 0x80010001L\n\nevent_names = {\n    1: \'EXCEPTION_DEBUG_EVENT\',\n    2: \'CREATE_THREAD_DEBUG_EVENT\',\n    3: \'CREATE_PROCESS_DEBUG_EVENT\',\n    4: \'EXIT_THREAD_DEBUG_EVENT\',\n    5: \'EXIT_PROCESS_DEBUG_EVENT\',\n    6: \'LOAD_DLL_DEBUG_EVENT\',\n    7: \'UNLOAD_DLL_DEBUG_EVENT\',\n    8: \'OUTPUT_DEBUG_STRING_EVENT\',\n    9: \'RIP_EVENT\',\n}\n\nEXCEPTION_MAXIMUM_PARAMETERS = 15\n\nEXCEPTION_DATATYPE_MISALIGNMENT  = 0x80000002\nEXCEPTION_ACCESS_VIOLATION       = 0xC0000005\nEXCEPTION_ILLEGAL_INSTRUCTION    = 0xC000001D\nEXCEPTION_ARRAY_BOUNDS_EXCEEDED  = 0xC000008C\nEXCEPTION_INT_DIVIDE_BY_ZERO     = 0xC0000094\nEXCEPTION_INT_OVERFLOW           = 0xC0000095\nEXCEPTION_STACK_OVERFLOW         = 0xC00000FD\n\n\nclass EXCEPTION_DEBUG_INFO(Structure):\n    _fields_ = [\n        ("ExceptionCode", c_uint),\n        ("ExceptionFlags", c_uint),\n        ("ExceptionRecord", c_void_p),\n        ("ExceptionAddress", c_void_p),\n        ("NumberParameters", c_uint),\n        ("ExceptionInformation", c_void_p * EXCEPTION_MAXIMUM_PARAMETERS),\n    ]\n\nclass EXCEPTION_DEBUG_INFO(Structure):\n    _fields_ = [\n        (\'ExceptionRecord\', EXCEPTION_DEBUG_INFO),\n        (\'dwFirstChance\', c_uint),\n    ]\n\nclass DEBUG_EVENT_INFO(Union):\n    _fields_ = [\n        ("Exception", EXCEPTION_DEBUG_INFO),\n    ]\n\nclass DEBUG_EVENT(Structure):\n    _fields_ = [\n        (\'dwDebugEventCode\', c_uint),\n        (\'dwProcessId\', c_uint),\n        (\'dwThreadId\', c_uint),\n        (\'u\', DEBUG_EVENT_INFO)\n    ]\n\ndef run_with_debugger(args):\n    proc = subprocess.Popen(args, creationflags=1)\n    event = DEBUG_EVENT()\n\n    num_exception = 0\n\n    while True:\n        if WaitForDebugEvent(pointer(event), 10):\n            print event_names.get(event.dwDebugEventCode, \'Unknown Event %s\' % event.dwDebugEventCode)\n\n            if event.dwDebugEventCode == 1:\n                num_exception += 1\n\n                exception_code = event.u.Exception.ExceptionRecord.ExceptionCode\n\n                if exception_code == 0x80000003L:\n                    print "Unknow exception:", hex(exception_code)\n\n                else:\n                    if exception_code == EXCEPTION_ACCESS_VIOLATION:\n                        print "EXCEPTION_ACCESS_VIOLATION"\n\n                    elif exception_code == EXCEPTION_INT_DIVIDE_BY_ZERO:\n                        print "EXCEPTION_INT_DIVIDE_BY_ZERO"\n\n                    elif exception_code == EXCEPTION_STACK_OVERFLOW:\n                        print "EXCEPTION_STACK_OVERFLOW"\n\n                    else:\n                        print "Other exception:", hex(exception_code)\n\n                    break\n\n            ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)\n\n        retcode = proc.poll()\n        if retcode is not None:\n            return retcode\n\nrun_with_debugger([\'crash.exe\'])\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/78048', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/13967/']