2013-11-01 1 views
5
에서 관리 예외를 잡기

그것이 관리 예외가 을 던져 관리 코드에 걸려 있지만, 어디 개입 기본 프레임이 호출 스택에가있을 수 있습니까?는 기본 프레임

이 작업을 수행하는 데 문제가 있습니다. 응용 프로그램은 32 비트 네이티브 코드이며 MSCLR 2.0을 호스팅합니다. 그러나 대부분의 코드는 .NET 3.5입니다.

이 throw가 완료되지 않으면 응용 프로그램이 제대로 실행되고 던지기 만하면 정확히 실행됩니다. 시스템을 실행 중입니다.

실제 응용 프로그램은 상당히 복잡하므로 처음에는 일러스트레이션을 위해 간단한 개념 코드를 게시 할 것입니다. 네이티브 프로그램 (Native.exe)은 하나의 관리되는 프로그램을 실행하며 Managed.exe이라고합니다. 어딘가 Managed.exe 내에서, C#으로 작성된, 다음입니다 :

class MyException : Exception {} 

... 

void OuterManaged() 
{ 
    MyObject.MyEvent += (s, a) => 
    { 
     Console.WriteLine("Throwing..."); 
     throw new MyException(); 
    } 

    try 
    { 
     MyKernel.DoSomething(); 
     Console.WriteLine("Finished"); 
    } catch(MyException) 
    { 
     Console.WriteLine("Caught"); 
    } 
} 

MyKernel 우리가 Glue.dll 전화 할게 ++/CLI 어셈블리 혼합 C에 정의 된 관리 클래스입니다. MyObjectGlue.dll에 다른 클래스의 인스턴스입니다.

void DoSomething(void) 
{ 
    _pMyNativeKernel->DoSomething(); 
} 

DoSomething 사실상라고 Native.exe에서 C++ 함수 : 거기에 관련하는 메소드는 다음과 같이 보인다. 긴 이야기를 짧게하기 위해 결국 Glue.dll의 관리 방법을 다시 호출하여 MyEvent을 발생시킵니다. 윈도우 7 64 비트 시스템에서 실행

Throwing... 
Caught 

을 내가 대신 : MyEvent가 발생하고 프로그램이 32 비트 Windows XP 시스템에서 실행중인

경우 의도 콘솔이 표시됩니다, 그것은 작동 이것을 얻으십시오 :

Throwing... 
Finished 

기본적으로, 예외는 다만 허공으로 사라집니다. 모든 일은 결코 일어난 적이없는 것처럼 계속 실행됩니다.

Throwing... 
: (. 예외는 창 닫기 버튼을 눌렀을에 해당하는, 그래서 그냥 버튼을 클릭하지 않은 것처럼 역할)

원격 데스크톱을 통해 윈도우 서버 2012 시스템을 실행,이 수 대화 상자가 말하는 "Native.exe의 작동이 중지되었습니다"이와

그리고 전체 응용 프로그램이 충돌은 :

Description: 
    Stopped working 

Problem signature: 
    Problem Event Name: CLR20r3 
    Problem Signature 01: Native.exe 
    Problem Signature 02: 0.0.0.0 
    Problem Signature 03: 5267c484 
    Problem Signature 04: 0 
    Problem Signature 05: 1.0.0.0 
    Problem Signature 06: 5272e299 
    Problem Signature 07: 208 
    Problem Signature 08: f 
    Problem Signature 09: MyException 
    OS Version: 6.2.9200.2.0.0.144.8 
    Locale ID: 1033 

이 내가이 try/catch 없었다고 기대했을 것입니다.

VS2008SP 디버거에서 해당 환경에서 실행할 경우 디버거가 첫 번째 예외를 catch하고 계속하면 처리되지 않은 예외로 catch합니다.

네이티브 DoSomething은 결국 Win32 GetMessage을 호출하고 DispatchMessage을 호출하고 네이티브 관리 식 콜백은 창 프로 시저에서 호출 된 코드에서 발생합니다. 이 창은 Direct3D로 그려져 있습니다.관리되는 프로그램은 모든 윈도우 및 그리기 작업에 Native.exe "커널"을 사용하며 Windows 자체는 액세스하지 않습니다. Native.exe 캐치 전혀 예외의 중간 기능의

없음. Win32 API 함수에 예외 처리기가 있는지 말할 수 없습니다. 그렇게 생각하지는 않겠지 만 그럴 경우 행동이 시스템간에 어떻게 모순되는지 설명 할 수 있습니다. 반복적 인 항목을 잘라와

이것은 대략 서버 2012의 실제 호출 스택입니다 :이 모든 시스템은 오랜 시간 동안 잘 작동하고있다

Managed!MyGame.ReInitDisplay.AnonymousMethod(object s = {Engine.Display}, System.EventArgs a = {System.EventArgs}) C# // throw site 
Glue.dll!CDisplayBridge::OnClosePressed() C++ 
[Native to Managed Transition] 
Native.EXE!EngineKern::CGfxDisplay_a::HandleClosePress() C++ 
Native.EXE!EngineKern::CGfxDisplay::WindowProc(HWND__ * hwnd=0x000610ac, unsigned int uMsg=16, unsigned int wParam=0, long lParam=0) C++ 
user32.dll!74a477d8() 
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]  
user32.dll!74a47c44() 
ntdll.dll!773e2f02()  
user32.dll!74a48fed() 
uxtheme.dll!7422254d() 
user32.dll!74a475e7() // DefWindowProc 
Native.EXE!EngineKern::CGfxDisplay::WindowProc(HWND__ * hwnd=0x000610ac, unsigned int uMsg=274, unsigned int wParam=61536, long lParam=4261024) C++ 
user32.dll!74a48a66() // DispatchMessage 
Native.EXE!EngineKern::CKernel::DoEvent() C++ 
[Managed to Native Transition] 
Glue.dll!Engine::Kernel::DoEvent() C++ // DoSomething in the example 
MyClassLib!MyClassLib.Game.MainLoop() C# 
MyClassLib!MyClassLib.Game.Play() C# 
Managed!MyGame.Play() C# 
Managed!Program.Main(string[] args = {string[0]}) C# 
mscorlib.dll!System.AppDomain.ExecuteAssemblyByName(string assemblyName, System.Security.Policy.Evidence assemblySecurity, string[] args) 
mscorlib.dll!System.AppDomain.ExecuteAssemblyByName(string assemblyName) 
Glue.dll!__Engine__::AppDomainManager::Main(int pEngineKern = 15760932) C++ 
[Native to Managed Transition] 
Native.EXE!EngineGlue::IManagedEntryPoint::Main(long pEngineKern=15760932) C++ // calls in by COM interop 
Native.EXE!CClrHost::Run() C++ 
Native.EXE!wWinMain(HINSTANCE__ * hInstance=0x00e40000, HINSTANCE__ * hPrevInstance=0x00000000, wchar_t * lpCmdLine=0x01462a80, int nCmdShow=5) C++ 
Native.EXE!__tmainCRTStartup() C 
Native.EXE!wWinMainCRTStartup() C 
kernel32.dll!74ca8543()  
ntdll.dll!773fac3c()  

하지만 관리를 통해 나는 예외를 던질 필요하지 않습니다/이전의 네이티브 트랜지션. 네이티브 호스트가 네이티브에서 관리되는 콜백을 수행하는지 여부를 염려하지 않고 관리되는 응용 프로그램 코드에서 예외를 자유롭게 포착하고 catch 할 수 있기를 바랍니다.

내가 온라인 등의 전환을 통해 예외를 던지는에 대한 찾을 모든 정보가 네이티브 예외 또는 그 반대의 캐치를 관리하는 데 대해 항상이다. 이는 관리되는 catching 관리이지만 간섭하는 네이티브 프레임은 문제를 복잡하게 만듭니다.

그래서 일반적으로 다음과 같이 던지는에 관해서 내 질문은 :

  • 이 일을해야 하는가? 이 은 Windows XP에서으로 작동하지만 잘 정의 된 동작인지 아니면 운이 좋았는지는 알 수 없습니다.

  • 일 경우 모든 시스템에서 작동하지 않는 이유는 무엇입니까?

이 있다면 하지 다음 내가, 관리 예외를 잡기 위해 모든 관리 답신 전화를 증대 네이티브 예외로 포장 등에 대한 관리되는 래퍼에서 그것을 잡을해야 할 것 같아요 작동하도록되어 네이티브 함수와 원래의 관리 예외를 throw합니다. 머리카락을 많이 당기는 것처럼 들리네!

+1

당신이 설명하는 문제는 http://stackoverflow.com/questions/6124631/clr-hosting-exception-handling-in-a-non-clr-created- 관련이있을 수 있습니다 thread? rq = 1. 관리되는 스레드에서 항상 콜백을 실행하는 데 도움이되는지 확인하십시오. – archgl

+0

@archgl 팁 주셔서 감사. 제 경우에는 _unhandled_ 예외가 아니지만 다른 질문에 단서가 있습니다. 어쩌면 일어나는 일은 네이티브 프레임으로 인해 SEH 예외가되어 외부 관리 프레임이 catch를하지 않기 때문입니다. 오직 SEH가 아닌 원래 관리되는 예외를 잡으려고합니다. 나는 그것보다 더 똑똑하기를 바랐다. (M-> N 썽크 _ SEH를 잡아서 관리로 되돌려 야한다. 별도의 스레드에서 다시 호출하면 실제로 외부 관리 코드에서 예외를 _ 판단 할 수 없습니다. – Kevin

답변

0

나는 동일한 문제를 다루고 있습니다. 폼, 즉 호출하는 코드 (또는 .ShowDialog()를 호출하는 코드)는 해당 catch() 블록이있는 try {} 블록 안에 있습니다. 어떤 시점에서 버튼을 클릭하면 대화 상자에서 예외가 발생하지만 캐치가 히트되지 않습니다!

그래서 나는 코드를 편집하고 간단하게 자신의 시도/캐치와 함께합니다 (의 OnClick 핸들러에서, 변환)을 일으키는 문을 둘러싸여 있습니다.

'catch'가 맞았지만 내부에는 'throw'가 있습니다. User-Unhandled 예외가 발생합니다!

내가 스택을 보면, 여러 관리/기본/관리 전환이 있습니다.

그것은 관리 스택에는 핸들러가 없다는 것을 시스템이 다음 관리 프레임 기본 프레임을 통해 스택을 걷지 않는 것 같다, 그래서 더 처리기 수없는 것으로 간주합니다. 예외가 네이티브 스레드에서 트리거되면