Frage

Was ist der beste Weg, um einen Absturz der Anwendung in XP (produziert das gleiche Paar von ‚Fehlern‘ Fenstern jedes Mal - jeweils mit gleichen Fenstertiteln) zu erkennen? Und dann neu starten

Ich bin besonders interessiert an Lösungen zu hören, die minimalen Systemressourcen, da das System in Frage verwendet, ist ziemlich alt.

hatte ich gedacht, von einer Skriptsprache wie AutoIt mit ( http://www.autoitscript.com/autoit3/ ) und Auslösen vielleicht ein ‚Detektor‘ Skript alle paar Minuten?

Wäre dies besser in Python, Perl, Powershell oder etwas ganz anderes zu tun?

Alle Ideen, Tipps oder Gedanken sehr geschätzt.

EDIT: Es ist nicht wirklich zum Absturz bringen (das heißt exit / beenden - dank @tialaramex). Es wird ein Dialog für die Benutzereingabe wartet, von einem weiteren Dialog folgte für weitere Benutzereingabe wartet, dann tatsächlich verlässt es. Es sind diese Dialoge, die Ich mag würde erkennen und zu behandeln.

War es hilfreich?

Lösung

Wie wäre es ein Wrapper-Anwendung erstellen, die die fehlerhafte Anwendung als Kind startet und wartet auf sie? Wenn der Exit-Code des Kindes einen Fehler anzeigt, dann starten Sie es, sonst verlassen.

Andere Tipps

Der beste Weg ist es, einen Namen zu verwenden, Mutex .

  1. Starten Sie Ihre Anwendung.
  2. Erstellen Sie einen neuen benannte Mutex und den Besitz über sie
  3. Starten Sie einen neuen Prozess (Prozess nicht Thread) oder eine neue Anwendung, was Sie preffer.
  4. Von dieser Prozess / Anwendung versuchen, den Mutex zu erwerben. Der Prozess wird Block
  5. Bei Anwendung beenden Freigabe des Mutex (Signal it)
  6. Die „Kontrolle“ Prozess wird nur die Mutex erwerben, wenn entweder die Anwendung beendet oder stürzt die Anwendung ab.
  7. Testen Sie den resultierenden Zustand nach dem Mutex aquiring. Wenn die Anwendung abgestürzt wird es WAIT_ABANDONED
  8. werden

Erklärung: Wenn ein Thread beendet, ohne dass der Mutex ein anderes Verfahren der Freigabe wartet, dass es es erwerben kann, aber es wird ein WAIT_ABANDONED als Rückgabewert, also die Mutex erhalten wird aufgegeben und therfore des Zustand der Abschnitt geschützt wurde, kann gefährlich sein.

Auf diese Weise Ihre zweite App wird keine CPU-Zyklen nicht verbrauchen, wie es für den Mutex warten halten (und das ist enterely vom Betriebssystem behandelt werden)

Ich denke, das Hauptproblem ist, dass Dr. Watson zeigt einen Dialog und hält Ihren Prozess am Leben.

Sie können Ihren eigenen Debugger mit dem Windows-API schreiben und Führen Sie den Absturz Anwendung von dort aus. Dies wird andere Debugger verhindern, fangen den Absturz Ihre Anwendung und Sie können auch das Ausnahmeereignis fangen.

Da ich keinen Beispielcode gefunden habe, habe ich geschrieben die Python quick-and-dirty Probe. Ich bin nicht sicher, wie robust es ist insbesondere die Erklärung von DEBUG_EVENT verbessert werden könnte.

from ctypes import windll, c_int, Structure
import subprocess

WaitForDebugEvent = windll.kernel32.WaitForDebugEvent    
ContinueDebugEvent = windll.kernel32.ContinueDebugEvent
DBG_CONTINUE = 0x00010002L    
DBG_EXCEPTION_NOT_HANDLED = 0x80010001L

event_names = {    
    3: 'CREATE_PROCESS_DEBUG_EVENT',
    2: 'CREATE_THREAD_DEBUG_EVENT',
    1: 'EXCEPTION_DEBUG_EVENT',
    5: 'EXIT_PROCESS_DEBUG_EVENT',
    4: 'EXIT_THREAD_DEBUG_EVENT',
    6: 'LOAD_DLL_DEBUG_EVENT',
    8: 'OUTPUT_DEBUG_STRING_EVENT', 
    9: 'RIP_EVENT',
    7: 'UNLOAD_DLL_DEBUG_EVENT',
}
class DEBUG_EVENT(Structure):
    _fields_ = [
        ('dwDebugEventCode', c_int),
        ('dwProcessId', c_int),
        ('dwThreadId', c_int),
        ('u', c_int*20)]

def run_with_debugger(args):
    proc = subprocess.Popen(args, creationflags=1)
    event = DEBUG_EVENT()

    while True:
        if WaitForDebugEvent(pointer(event), 10):
            print event_names.get(event.dwDebugEventCode, 
                    'Unknown Event %s' % event.dwDebugEventCode)
            ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)
        retcode = proc.poll()
        if retcode is not None:
            return retcode

run_with_debugger(['python', 'crash.py'])

Ich weiß, dass Sie mit Windows XP zu tun hat, aber für die Menschen in einer ähnlichen Situation unter Vista gibt es neue Crash Recovery API s zur Verfügung. Hier ist ein gute Einführung zu dem, was sie tun können.

Hier ist eine leicht verbesserte Version.

In meinem Test der vorherige Code in einer Endlosschleife laufen, wenn der fehlerhafte exe eine „Zugriffsverletzung“ erzeugt wird.

ich durch meine Lösung nicht ganz zufrieden bin, weil ich keine klaren Kriterien wissen, welche Ausnahme fortgesetzt werden sollte und welche nicht (Die ExceptionFlags sind keine Hilfe) sein könnte.

Aber es funktioniert am Beispiel I ausgeführt werden.

Hoffe, es hilft, Vivian De Smedt

from ctypes import windll, c_uint, c_void_p, Structure, Union, pointer
import subprocess

WaitForDebugEvent = windll.kernel32.WaitForDebugEvent
ContinueDebugEvent = windll.kernel32.ContinueDebugEvent
DBG_CONTINUE = 0x00010002L
DBG_EXCEPTION_NOT_HANDLED = 0x80010001L

event_names = {
    1: 'EXCEPTION_DEBUG_EVENT',
    2: 'CREATE_THREAD_DEBUG_EVENT',
    3: 'CREATE_PROCESS_DEBUG_EVENT',
    4: 'EXIT_THREAD_DEBUG_EVENT',
    5: 'EXIT_PROCESS_DEBUG_EVENT',
    6: 'LOAD_DLL_DEBUG_EVENT',
    7: 'UNLOAD_DLL_DEBUG_EVENT',
    8: 'OUTPUT_DEBUG_STRING_EVENT',
    9: 'RIP_EVENT',
}

EXCEPTION_MAXIMUM_PARAMETERS = 15

EXCEPTION_DATATYPE_MISALIGNMENT  = 0x80000002
EXCEPTION_ACCESS_VIOLATION       = 0xC0000005
EXCEPTION_ILLEGAL_INSTRUCTION    = 0xC000001D
EXCEPTION_ARRAY_BOUNDS_EXCEEDED  = 0xC000008C
EXCEPTION_INT_DIVIDE_BY_ZERO     = 0xC0000094
EXCEPTION_INT_OVERFLOW           = 0xC0000095
EXCEPTION_STACK_OVERFLOW         = 0xC00000FD


class EXCEPTION_DEBUG_INFO(Structure):
    _fields_ = [
        ("ExceptionCode", c_uint),
        ("ExceptionFlags", c_uint),
        ("ExceptionRecord", c_void_p),
        ("ExceptionAddress", c_void_p),
        ("NumberParameters", c_uint),
        ("ExceptionInformation", c_void_p * EXCEPTION_MAXIMUM_PARAMETERS),
    ]

class EXCEPTION_DEBUG_INFO(Structure):
    _fields_ = [
        ('ExceptionRecord', EXCEPTION_DEBUG_INFO),
        ('dwFirstChance', c_uint),
    ]

class DEBUG_EVENT_INFO(Union):
    _fields_ = [
        ("Exception", EXCEPTION_DEBUG_INFO),
    ]

class DEBUG_EVENT(Structure):
    _fields_ = [
        ('dwDebugEventCode', c_uint),
        ('dwProcessId', c_uint),
        ('dwThreadId', c_uint),
        ('u', DEBUG_EVENT_INFO)
    ]

def run_with_debugger(args):
    proc = subprocess.Popen(args, creationflags=1)
    event = DEBUG_EVENT()

    num_exception = 0

    while True:
        if WaitForDebugEvent(pointer(event), 10):
            print event_names.get(event.dwDebugEventCode, 'Unknown Event %s' % event.dwDebugEventCode)

            if event.dwDebugEventCode == 1:
                num_exception += 1

                exception_code = event.u.Exception.ExceptionRecord.ExceptionCode

                if exception_code == 0x80000003L:
                    print "Unknow exception:", hex(exception_code)

                else:
                    if exception_code == EXCEPTION_ACCESS_VIOLATION:
                        print "EXCEPTION_ACCESS_VIOLATION"

                    elif exception_code == EXCEPTION_INT_DIVIDE_BY_ZERO:
                        print "EXCEPTION_INT_DIVIDE_BY_ZERO"

                    elif exception_code == EXCEPTION_STACK_OVERFLOW:
                        print "EXCEPTION_STACK_OVERFLOW"

                    else:
                        print "Other exception:", hex(exception_code)

                    break

            ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE)

        retcode = proc.poll()
        if retcode is not None:
            return retcode

run_with_debugger(['crash.exe'])
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top