Development Tip

VS2010은 Windows 64 비트 버전의 WinForms 응용 프로그램에서 처리되지 않은 예외 메시지를 표시하지 않습니다.

yourdevel 2020. 10. 16. 08:12
반응형

VS2010은 Windows 64 비트 버전의 WinForms 응용 프로그램에서 처리되지 않은 예외 메시지를 표시하지 않습니다.


새 프로젝트를 만들 때 처리되지 않은 예외에 대해 이상한 동작이 발생합니다. 문제를 재현하는 방법은 다음과 같습니다.

1) 새 Windows Forms 응용 프로그램 만들기 (C #, .NET Framework 4, VS2010)

2) Form1_Load핸들러에 다음 코드를 추가하십시오 .

int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;

VS가 중단되고 두 번째 줄에 처리되지 않은 예외 메시지가 표시 될 것으로 예상합니다. 그러나 세 번째 줄은 메시지없이 건너 뛰고 응용 프로그램이 계속 실행됩니다.

기존 C # 프로젝트에는이 문제가 없습니다. 그래서 내 새 프로젝트가 이상한 기본 설정으로 생성되었다고 생각합니다.

누구든지 내 프로젝트에 무엇이 잘못되었는지 알고 있습니까 ???

Debug-> Exceptions의 확인란을 선택해 보았습니다. 그러나 try-catch블록 에서 예외를 처리하더라도 실행이 중단됩니다 . 그것은 또한 내가 원하는 것이 아닙니다. 내가 올바르게 기억한다면,이 대화 상자에 "처리되지 않은 예외"또는 이와 유사한 열이 있었는데,이 열은 내가 원하는 것을 정확하게 수행합니다. 하지만 내 프로젝트에는 단 하나의 열 ( "Thrown") 만 있습니다.


이것은 64 비트 버전의 Windows 7에서 32 비트 코드를 실행할 수 있도록하는 wow64 에뮬레이션 레이어에 의해 유발 된 불쾌한 문제입니다. 64 비트 창 관리자가 생성 한 알림에 대한 응답으로 실행되는 코드의 예외를 삼 킵니다. , Load이벤트 처럼 . 디버거가이를 인식하지 못하도록 방지합니다.이 문제는 해결하기 어렵습니다. Microsoft의 Windows 및 DevDiv 그룹은 손가락을 앞뒤로 가리키고 있습니다. DevDiv는 그것에 대해 아무것도 할 수 없으며 Windows는 그것이 정확하고 문서화 된 행동이라고 생각합니다.

확실히 문서화되어 있지만 그 결과를 이해하거나 합리적인 행동이라고 생각하는 사람은 거의 없습니다. 특히 래퍼 클래스를 사용하여 창 배관을 숨기는 모든 프로젝트 에서처럼 창 프로 시저가보기에서 숨겨지는 경우에는 특히 그렇습니다. 모든 Winforms, WPF 또는 MFC 앱과 마찬가지로. 근본적인 문제는 Microsoft가 32 비트 코드에서 예외를 처리하거나 디버그하려는 32 비트 코드로 알림을 트리거 한 64 비트 코드로 다시 보내는 방법을 알아낼 수 없다는 것입니다.

디버거가 연결된 경우에만 문제가 있으며 코드가 없으면 평소와 같이 폭파됩니다.

프로젝트> 속성> 빌드 탭> 플랫폼 대상 = AnyCPU 및 32 비트 선호를 선택 취소합니다. 이제 앱이 64 비트 프로세스로 실행되어 wow64 오류 모드가 제거됩니다. 일부 결과는 VS2013 이전의 VS 버전에 대해 편집 + 계속을 비활성화하고 32 비트 코드에 대한 종속성이있는 경우 항상 가능하지 않을 수 있습니다.

기타 가능한 해결 방법 :

  • 디버그> 예외> CLR 예외에 대한 throw 상자를 선택하여 예외를 throw하는 코드 줄에서 디버거를 강제로 중지합니다.
  • Load이벤트 핸들러 에 try / catch를 작성 하고 catch 블록에 failfast를 작성합니다.
  • 메시지 루프의 예외 트랩이 디버그 모드에서 비활성화되지 않도록 메서드 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)에서 사용 Main()합니다. 그러나 이것은 처리되지 않은 모든 예외를 디버그하기 어렵게 만들고 ThreadException이벤트는 거의 쓸모가 없습니다.
  • 코드가 실제로 Load이벤트 핸들러에 속하는지 고려하십시오 . 필요한 경우는 매우 드뭅니다. 그러나 기본 이벤트이고 두 번 클릭하면 이벤트 처리기가 추가되기 때문에 VB.NET 및 백조 노래에서 매우 인기가 있습니다. 사용자 환경 설정 및 자동 크기 조정이 적용된 후 실제 창 크기에 관심 있을 때만 실제로 필요합니다 Load. 다른 모든 것은 생성자에 속합니다.
  • Windows 8 이상으로 업데이트하면이 wow64 문제가 해결되었습니다.

내 경험상 디버거가 연결된 상태에서 실행할 때만이 문제가 나타납니다. 응용 프로그램은 독립 실행 형으로 실행될 때 동일하게 작동합니다. 예외는 삼키지 않습니다.

KB976038 의 도입으로 다시 예상 대로이 작업을 수행 할 수 있습니다. 핫픽스를 설치 한 적이 없으므로 Win7 SP1의 일부로 제공된 것으로 가정합니다.

이것은이 게시물에서 언급되었습니다.

핫픽스를 활성화하는 코드는 다음과 같습니다.

public static class Kernel32
{
    public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;

    [DllImport("Kernel32.dll")]
    public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);

    [DllImport("Kernel32.dll")]
    public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);


    public static void DisableUMCallbackFilter() {
        uint flags;
        GetProcessUserModeExceptionPolicy(out flags);

        flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
        SetProcessUserModeExceptionPolicy(flags);
    }
}

응용 프로그램 시작시 호출하십시오.

    [STAThread]
    static void Main()
    {
        Kernel32.DisableUMCallbackFilter();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

아래에 표시된 간단한 예를 통해 예상대로 작동 함을 확인했습니다.

protected override void OnLoad(EventArgs e) {
    throw new Exception("BOOM");   // This will now get caught.
}

그래서, 제가 이해하지 못하는 것은 이전에는 디버거가 커널 모드 스택 프레임 교차를 처리하는 것이 불가능했던 이유입니다. 그러나이 핫픽스를 통해 그들은 어떻게 든 알아 냈습니다.


Hans가 언급했듯이 응용 프로그램을 컴파일하고 디버거를 연결하지 않고 exe를 실행하십시오.

나에게 문제는 BindingSource 컨트롤이 바인딩 된 Class 속성 이름을 변경하는 것입니다. IDE없이 실행하면 오류가 표시됩니다.

DataSource 의 속성 또는 열 SendWithoutProofReading바인딩 할 수 없습니다 . 매개 변수 이름 : dataMember

BindingSource 컨트롤을 수정하여 업데이트 된 속성 이름에 바인딩하면 문제가 해결되었습니다. enter image description here


나는 WPF를 사용하고 있으며 이와 동일한 문제가 발생했습니다. 나는 Hans 1-3 제안을 이미 시도했지만 스튜디오가 오류가있는 곳에서 멈추지 않기 때문에 마음에 들지 않았습니다 (그래서 내 변수를 볼 수 없었고 문제가 무엇인지 볼 수 없었습니다).

So I tried Hans' 4th suggestion. I was suprised at how much of my code could be moved to the MainWindow constructor without any issue. Not sure why I got in the habit of putting so much logic in the Load event, but apparently much of it can be done in the ctor.

However, this had the same problem as 1-3. Errors that occur during the ctor for WPF get wrapped into a generic Xaml exception. (an inner exception has the real error, but again I wanted studio to just break at the actual trouble spot).

What ended up working for me was to create a thread, sleep 50ms, dispatch back to main thread and do what I need...

    void Window_Loaded(object sender, RoutedEventArgs e)
    {
        new Thread(() =>
        {
            Thread.Sleep(50);
            CrossThread(() => { OnWindowLoaded(); });
        }).Start();
    }
    void CrossThread(Action a)
    {
        this.Dispatcher.BeginInvoke(a);
    }
    void OnWindowLoaded()
    {
        ...do my thing...

This way studio would break right where an uncaught exception occurs.


A simple work-around could be if you can move your init code to another event like as Form_Shown which called later than Form_Load, and use a flag to run startup code at first form shown:

bool firstLoad = true; //flag to detect first form_shown

private void Form1_Load(object sender, EventArgs e)
{
    //firstLoad = true;
    //dowork(); //not execute initialization code here (postpone it to form_shown)
}

private void Form1_Shown(object sender, EventArgs e)
{
    if (firstLoad) //simulate Form-Load
    {
        firstLoad = false;

        dowork();
    }
}

void dowork()
{
    var f = File.OpenRead(@"D:\NoSuchFile756.123"); //this cause an exception!

}

참고URL : https://stackoverflow.com/questions/4933958/vs2010-does-not-show-unhandled-exception-message-in-a-winforms-application-on-a

반응형