2010-08-05 4 views
6

우리는 타사 API를 사용하여 CAD 파일을 읽는 관리되지 않는 C++ 응용 프로그램을 보유하고 있습니다. 손상된 특정 CAD 파일에서 타사 라이브러리가 충돌하고 EXE 파일이 다운됩니다. 이 때문에 우리의 주요 응용 프로그램은 별도의 EXE이며 이런 식으로 충돌의 영향을받지 않습니다. 그렇지만 우리는 짜증나는 Microsoft 오류보고 대화 상자로 끝납니다.하나의 앱에 대해 Microsoft 오류보고를 방지 할 수 있습니까?

Microsoft 오류보고 시스템을 사용하지 않도록 설정하고 싶지 않습니다. 단일 응용 프로그램에 대한 오류보고 기능을 해제하여 충돌이 발생하면 오류 팝업 대화 상자없이 자동으로 충돌이 발생하지 않도록 할 수 있습니까?

답변

0

전혀 모르겠지만 아마도 SetErrorMode 또는 SetThreadErrorMode이 효과가 있습니까?

+0

추가 참고,이 충돌은 처리되지 않은 구조적 예외 (액세스 위반, 스택 오버플로 등)에 의해 발생되는 경우 구조화 된 예외 처리기를 사용하여 조사 할 수 있습니다. 그것들을 사용하여 정보를 기록하고 자동으로 충돌하거나 다른 작업을 수행 할 수 있습니다. –

5

Vista 이상에서는 WerAddExcludedApplication API 함수를 사용하여 지정된 응용 프로그램 실행 파일을 오류보고에서 제외 할 수 있습니다. 내가 아는 한 XP 및 다른 레거시 OS 버전에는 비슷한 옵션이 없습니다.

그러나 WER는 처리되지 않은 응용 프로그램 예외에서만 실행되므로 EXE에 "catch-all"예외 처리기를 추가하여이를 억제 할 수 있어야합니다. 달성 방법에 대한 아이디어는 vectored exception handling을 참조하십시오. 처리되지 않은 모든 예외를 억제하는 것은 일반적으로 나쁜 생각 (그리고, 예를 들어, 응용 프로그램은 Windows 로고 인증을 실패합니다) 당신이 무차별 적으로이 방법을 사용해서는 안 것을

주 ...

+0

WER API를 언급 한 경우 +1. – bk1e

5

그래, 거기 네가 할 수있는 일. main() 메서드에서 SetUnhandledExceptionFilter()를 호출하여 콜백을 등록하십시오. Microsoft WER 대화 상자가 나타나기 바로 전에 아무도 자원자가 예외를 처리하지 않을 때 호출됩니다.

실제로 콜백에서 뭔가하는 것은 문제가 있습니다. 이 프로그램은 항상 AccessViolation 예외처럼 심한 무언가로 죽었습니다. 힙 손상으로 인해 종종 방해를받습니다. 힙이 토스트 일 때 사용자에게 알려주는 메시지 상자를 표시하는 것과 같은 작업을하는 것은 번거로운 작업입니다. 교착 상태는 항상 아무런 진단없이 프로그램을 잠글 준비가되어 있습니다.

가장 안전한 방법은 기본 프로세스를 보호하는 도우미 프로세스를 만드는 것입니다. 콜백에서 이름이 지정된 이벤트를 신호로 알립니다. 메모리 매핑 된 파일에 필요한 예외 정보를 제공하십시오. 도우미는 이벤트가 신호를 받으면 원하는 모든 것을 할 수 있습니다. 메시지 표시하기, 미니 덤프 찍기. 그리고 주요 프로세스를 종료합니다.

정확히 Microsoft WerFault 도우미가 작동하는 방식은 다음과 같습니다.

+0

UEF는 일반적으로 문제가 많고 신뢰할 수 없습니다. 희소 한 상황이있을 때라도 시스템에 의해 다시 호출되지 않는 경우가 있습니다. 또한, 전역 적이며 건방진 셸 확장, 제 3 자 라이브러리 등으로 덮어 쓸 수도 있습니다. 사용자가 제안한 "WerAddExcludedApplication"을 호출하거나 "Jan_Noy"가 제안한'SetErrorMode'를'SEM_NOGPFAULTERRORBOX' ("Jan Goyvaerts") 둘 다 더 강력합니다. – Donpedro

5

한스 패스언트의 답변은 SetUnhandledExceptionFilter입니다. 그는 프로세스의 여러 부분이 불안정한 상태 일 수 있기 때문에 콜백 내에서 너무 많이 할 수 없다는 점에 대해 좋은 점을 제시합니다.

그러나 문제가 설명 된 방식에서 시스템에 정상적인 충돌 대화 상자를 표시하지 않는 것 외에는 아무 것도하지 않는 것처럼 들리지는 않습니다. 이 경우 충돌이 영향을 미칠 수있는 프로세스 부분에 관계없이 쉽고 안전해야합니다.

과 같은 기능 뭔가 확인 : (가능한 한 빨리 아마)

LONG WINAPI UnhandledExceptionCallback(PEXCEPTION_POINTERS pExceptPtrs) 
{ 
    if (IsDebuggerPresent()) 
     // Allow normal crash handling, which means the debugger will take over. 
     return EXCEPTION_CONTINUE_SEARCH; 
    else 
     // Say we've handled it, so that the standard crash dialog is inhibited. 
     return EXCEPTION_EXECUTE_HANDLER; 
} 

그리고 어딘가에 당신의 프로그램에서 콜백 설정 :

SetUnhandledExceptionFilter(UnhandledExceptionCallback); 

당신이 원하는 일을해야한다 - 어떤 허용 자동으로 죽을 특정 프로그램의 충돌.

그러나 타사 구성 요소 (DLL, OCX 등)를 가져올 때마다 그 중 하나도 SetUnhandledExceptionFilter를 호출 할 수 있으므로 자신의 콜백을 자신의 것으로 바꿀 위험성이 있습니다. . 한 번 인스턴스화 할 때 자체 콜백을 설정할 ActiveX 컨트롤을 발견했습니다. 그리고 더 나쁜 것은 원래의 콜백이 파괴되었을 때 원래 콜백을 복원하지 못했습니다. 그것은 그들의 코드에서 버그 인 것 같았지만 관계없이 내가 원하는 콜백이 적어도 컨트롤이 종료 된 후에 있어야한다고 확신 할 수 있도록 추가 조치를 취해야했습니다. 따라서 콜백을 올바르게 설정했음을 알았을 때도 이것이 때때로 작동하지 않는 것으로 밝혀지면 비슷한 결과가 발생할 수 있습니다.

+0

이것은 작동하지 않으며 처리 된 것이 없습니다. 오류 수정 명령을 다시 시작하여 같은 방법으로 충돌합니다. 무한 루프. –

+0

필자는 메모리를 조합하고 더 이상 오래된 코드를 발췌하여이 코드를 테스트 할 수있는 위치에 있지 않은 것으로 보았습니다. 하지만 난 그냥 NULL 포인터를 사용하여 시도하고 충돌로 만든 빠른 테스트 프로그램에 넣어 그것은 의도대로 작동하는 것 같습니다. 루프가 아니라 조용히 끝나는 것을보고 있습니다. 오류가있는 명령에서 재개되도록 EXCEPTION_CONTINUE_EXECUTION이되지 않습니까? – TheUndeadFish

+1

내가 잘못 본 것이 아니라면 디버거가있을 때 전혀 호출되지 않았으므로 UEF 콜백 ('IsDebuggerPresent')에 디버거가 있는지 확인할 필요가 없습니다. – Donpedro

2

델파이 애플리케이션을 개발하는 동안 나는이 상황에서 자신을 발견했습니다. 안정적으로 "앱이 작동을 멈췄습니다"대화 상자를 표시하지 않기 위해 두 가지가 필요하다는 것을 알았습니다.

SetErrorMode(SEM_NOGPFAULTERRORBOX);을 호출하면 "app has stopped working"대화 상자가 표시되지 않습니다. 그러나 Delphi의 예외 처리기는 대신 런타임 오류 메시지가 포함 된 메시지 상자를 표시합니다.

Delphi의 예외 처리기를 표시하지 않으려면 Halt을 호출하여 프로세스를 종료하는 사용자 지정 처리기로 SetUnhandledExceptionFilter을 호출합니다.

그래서 충돌로 발생하기 쉬운 코드를 실행하는 델파이 클라이언트 응용 프로그램에 대한 골격이된다 :

function HaltOnException(const ExceptionInfo: TExceptionPointers): Longint; stdcall; 
begin 
    Halt; 
    Result := 1; // Suppress compiler warning 
end; 

begin 
    SetErrorMode(SEM_NOGPFAULTERRORBOX); 
    SetUnhandledExceptionFilter(@HaltOnException); 
    try 
    DoSomethingThatMightCrash; 
    except 
    on E: Exception do 
     TellServerWeFailed(E.Message); 
    end; 
end. 
+0

Visual C++의 경우 SetErrorMode (SEM_NOGPFAULTERRORBOX)를 사용하는 경우가 대부분입니다. 충분하다. –

관련 문제