2008-09-16 28 views
9

Cách tốt nhất để phát hiện sự cố ứng dụng trong XP (tạo ra cùng một cặp cửa sổ 'lỗi' mỗi lần - mỗi cửa sổ có cùng tiêu đề cửa sổ) và sau đó khởi động lại nó?Cách tốt nhất để phát hiện sự cố ứng dụng và khởi động lại nó?

Tôi đặc biệt quan tâm đến việc nghe các giải pháp sử dụng tài nguyên hệ thống tối thiểu vì hệ thống được đề cập khá cũ.

Tôi đã nghĩ đến việc sử dụng ngôn ngữ kịch bản như AutoIt (http://www.autoitscript.com/autoit3/) và có thể kích hoạt tập lệnh 'dò tìm' sau mỗi vài phút?

Điều này có thực hiện tốt hơn trong Python, Perl, PowerShell hoặc một thứ khác hoàn toàn không?

Bất kỳ ý tưởng, mẹo hoặc suy nghĩ nào được đánh giá cao.

EDIT: Nó không thực sự sụp đổ (ví dụ: thoát/chấm dứt - cảm ơn @tialaramex). Nó sẽ hiển thị một hộp thoại chờ đầu vào của người dùng, theo sau là một hộp thoại khác đang chờ người dùng thêm vào, sau đó nó thực sự thoát. Đó là những hộp thoại mà tôi muốn phát hiện và xử lý.

+0

Liệu việc áp dụng thực sự sụp đổ (thoát, chấm dứt, không còn được chạy) hay nó hiển thị một hộp thoại báo lỗi và chờ đợi cho bạn để làm điều gì đó? – tialaramex

+0

Lỗi gì vậy? Gửi cho Microsoft, hoặc một số tùy chỉnh? – Suma

Trả lời

3

Cách tạo ứng dụng trình bao bọc khởi chạy ứng dụng bị lỗi khi còn nhỏ và đợi ứng dụng đó? Nếu mã thoát của đứa trẻ chỉ ra một lỗi, sau đó khởi động lại nó, thoát khác.

12

Cách tốt nhất là sử dụng tên mutex.

  1. Khởi động ứng dụng của bạn.
  2. Tạo một mutex mới có tên và sở hữu nó
  3. Bắt đầu một quy trình mới (xử lý không phải luồng) hoặc ứng dụng mới, những gì bạn muốn.
  4. Từ quy trình/ứng dụng đó cố gắng thu hút mutex. Quá trình này sẽ chặn
  5. Khi ứng dụng hoàn thành phát hành mutex (báo hiệu nó)
  6. Quy trình "kiểm soát" sẽ chỉ thu hút mutex nếu ứng dụng kết thúc hoặc ứng dụng gặp sự cố.
  7. Kiểm tra trạng thái kết quả sau khi yêu cầu mutex. Nếu ứng dụng đã bị rơi nó sẽ được WAIT_ABANDONED

Giải thích: Khi một thread kết thúc mà không phát hành các mutex bất kỳ quá trình khác đang chờ nó có thể aquire nó nhưng nó sẽ có được một WAIT_ABANDONED như giá trị trả về, có nghĩa là mutex là bị bỏ rơi và do đó trạng thái của phần được bảo vệ có thể không an toàn.

Bằng cách này ứng dụng thứ hai của bạn sẽ không tiêu thụ bất kỳ chu kỳ CPU vì nó sẽ tiếp tục chờ đợi cho các mutex (và đó là enterely xử lý bởi các hệ điều hành)

3

Tôi nghĩ vấn đề chính là Dr. Watson sẽ hiển thị hộp thoại và giữ cho quá trình của bạn luôn hoạt động.

Bạn có thể viết trình gỡ rối của riêng mình bằng cách sử dụng API Windows và chạy ứng dụng gặp sự cố từ đó. Điều này sẽ ngăn các trình gỡ rối khác bắt gặp sự cố ứng dụng của bạn và bạn cũng có thể nắm bắt sự kiện Ngoại lệ.

Vì tôi không tìm thấy bất kỳ mã mẫu nào, tôi đã viết mẫu Python nhanh chóng và bẩn này. Tôi không chắc chắn mức độ mạnh mẽ của nó là đặc biệt là việc khai báo DEBUG_EVENT có thể được cải thiện.

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

Đây là phiên bản được cải thiện một chút.

Trong thử nghiệm của tôi, mã trước chạy trong một vòng lặp vô hạn khi exe bị lỗi tạo ra "vi phạm truy cập".

Tôi không hoàn toàn hài lòng bởi giải pháp của mình vì tôi không có tiêu chí rõ ràng để biết nên tiếp tục ngoại lệ nào và ngoại lệ nào không được (The ExceptionFlags không giúp ích gì).

Nhưng nó hoạt động trên ví dụ tôi chạy.

Hy vọng nó giúp, 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']) 
Các vấn đề liên quan