Domanda

Qual è il modo migliore per rilevare un crash dell'applicazione in XP (produce la stessa coppia di "errore" windows ogni volta - ogni con lo stesso titolo della finestra) e poi riavviare?

Sono particolarmente interessato a sentire le soluzioni che utilizzano le risorse di sistema minime in quanto il sistema in questione è abbastanza vecchio.

Avevo pensato di usare un linguaggio di scripting come AutoIt (http://www.autoitscript.com/autoit3/), e, forse, l'attivazione di un 'rivelatore' script ogni pochi minuti?

Sarebbe meglio se fatto in Python, Perl, PowerShell o qualcosa di completamente diverso?

Idee, suggerimenti, o pensieri molto apprezzato.

EDIT:In realtà, non crash (es.uscita/fine - grazie @tialaramex).Visualizza una finestra di dialogo in attesa dell'input dell'utente, seguito da un'altra finestra in attesa di ulteriori input dell'utente, quindi termina effettivamente.Queste finestre di dialogo che vorrei rilevare e trattare.

È stato utile?

Soluzione

Come circa la creazione di un wrapper applicazione che lancia il difettoso app come un bambino e si aspetta?Se il codice di uscita del bambino indica un errore, riavviare, altrimenti esci.

Altri suggerimenti

Modo migliore è quello di utilizzare un nome mutex.

  1. Avviare l'applicazione.
  2. Creare un nuovo mutex denominato e prendere la proprietà su di esso
  3. Avviare un nuovo processo (processo non thread) o una nuova applicazione, che si preffer.
  4. Da tale processo / applicazione tenta di acquisire il mutex.Il processo di blocco
  5. Quando l'applicazione di finitura rilascia il mutex (segnale)
  6. Il "controllo" del processo solo acquisire il mutex se l'applicazione di finiture o l'applicazione si blocca.
  7. Prova lo stato risultante dopo acquisendo il mutex.Se la domanda era schiantato sarà WAIT_ABANDONED

Spiegazione: Quando un thread termina senza rilasciare il mutex qualsiasi altro processo in attesa che si possono acquisire, ma è ottenere un WAIT_ABANDONED come valore di ritorno, il che significa che il mutex viene abbandonato e pertanto lo stato della sezione è stato protetto può essere pericoloso.

In questo modo la tua seconda applicazione non consuma cicli di CPU come sarà tenere d'attesa per il mutex (e che è interamente gestita dal sistema operativo)

Credo che il problema principale è che il Dr.Watson visualizza una finestra di dialogo e mantiene il vostro processo di vita.

È possibile scrivere il proprio debugger utilizzando le API di Windows e eseguire il crash dell'applicazione da lì.Questo consentirà di evitare altri debugger, da dove prendere il crash di la domanda e si potrebbe anche prendere l'evento di Eccezione.

Dato che non ho trovato nessun codice di esempio, ho scritto questo Python quick-and-dirty campione.Io non sono sicuro di come robusto è in particolare la dichiarazione di DEBUG_EVENT potrebbe essere migliorata.

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'])

Mi rendo conto che hai a che fare con Windows XP, ma per le persone in una situazione simile in Vista, ci sono nuovi crash recovery APIs disponibili. Ecco una buona introduzione quello che possono fare.

Qui è una versione leggermente migliorata.

Nel mio test precedente l'esecuzione di codice in un ciclo infinito quando il guasto exe generato una "violazione di accesso".

Io non sono completamente soddisfatto con la mia soluzione, perché non ho criteri chiari per sapere quali eccezione deve essere continuato e che non si potrebbe essere (Il ExceptionFlags non è di nessun aiuto).

Ma funziona su l'esempio che ho eseguito.

Speranza che aiuta, 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'])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top