8

XP でアプリケーションのクラッシュを検出し (毎回同じ「エラー」ウィンドウのペアを生成し、それぞれ同じウィンドウ タイトルで)、それを再起動する最良の方法は何ですか?

問題のシステムはかなり古いため、最小限のシステム リソースを使用するソリューションについて聞くことに特に興味があります。

AutoIt ( http://www.autoitscript.com/autoit3/ ) のようなスクリプト言語を使用して、おそらく数分ごとに「検出」スクリプトをトリガーすることを考えていましたか?

これは、Python、Perl、PowerShell、またはまったく別の方法で行う方がよいでしょうか?

アイデア、ヒント、または考えは大歓迎です。

編集:実際にはクラッシュしません(つまり、終了/終了-@tialaramexに感謝します)。ユーザー入力を待っているダイアログが表示され、さらにユーザー入力を待っている別のダイアログが続き、実際に終了します。私が検出して対処したいのは、これらのダイアログです。

4

5 に答える 5

13

最善の方法は、名前付きミューテックスを使用することです。

  1. アプリケーションを開始します。
  2. 新しい名前付きミューテックスを作成し、所有権を取得します
  3. 新しいプロセス (スレッドではなくプロセス) または新しいアプリケーションを開始します。
  4. そのプロセス/アプリケーションからミューテックスを取得しようとします。プロセスがブロックされます
  5. アプリケーションが終了したら、mutex を解放します (シグナルを送ります)
  6. 「制御」プロセスは、アプリケーションが終了するかアプリケーションがクラッシュした場合にのみミューテックスを取得します。
  7. ミューテックスを取得した後、結果の状態をテストします。アプリケーションがクラッシュした場合、WAIT_ABANDONED になります。

説明:スレッドがミューテックスを解放せずに終了すると、それを待っている他のプロセスはそれを取得できますが、戻り値として WAIT_ABANDONED を取得します。これは、ミューテックスが放棄され、したがって、保護されていたセクションの状態が安全でない可能性があることを意味します。

このようにして、2 番目のアプリはミューテックスを待機し続けるため、CPU サイクルを消費しません (オペレーティング システムによって完全に処理されます)。

于 2008-09-16T23:12:16.757 に答える
3

障害のあるアプリを子として起動し、それを待機するラッパー アプリケーションを作成するのはどうですか? 子の終了コードがエラーを示している場合は再起動し、そうでない場合は終了します。

于 2008-09-16T22:48:07.503 に答える
2

Windows XP を扱っていることは承知していますが、Vista で同様の状況にある人のために、新しいクラッシュ リカバリ APIが利用可能です。 ここでは、彼らができることの良い紹介です。

于 2008-09-17T18:17:24.087 に答える
2

こちらは少し改良版。

私のテストでは、障害のあるexeが「アクセス違反」を生成したときに、前のコードが無限ループで実行されました。

どの例外を継続する必要があり、どの例外を継続できないかを判断する明確な基準がないため、私は自分のソリューションに完全に満足していません (ExceptionFlags は役に立ちません)。

しかし、私が実行した例では機能します。

お役に立てば幸いです、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'])
于 2009-06-04T10:14:10.310 に答える