qshinoの日記

Powershell関係と徒然なこと

wpf例外処理

Wpf例外処理

UIスレッドで発生した例外処理。

  1. 例外発生時、Try-catchより先に受け取るAppDomain.CurrentDomain.FirstChanceException
  2. UIスレッド DispatcherUnhandledException e.Handled = $true により例外処理済みにできる。
  3. バックグラウンドジョブ UnobservedTaskException UnobservedTaskExceptionEventArgsオブジェクト(System.Threading.Tasks名前空間)のSetObservedメソッドにより処理済みにできる。
  4. 最後の最後に AppDomainクラスのUnhandledExceptionイベント

DispatcherUnhandledException

public partial class App : Application
{
  public App()
  {
    // UIスレッドで実行されているコードで処理されなかったら発生する(.NET 3.0より)
    this.DispatcherUnhandledException += App_DispatcherUnhandledException;
  }

  private void App_DispatcherUnhandledException(
                  object sender, 
                  System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
  {
    string errorMember = e.Exception.TargetSite.Name;
    string errorMessage = e.Exception.Message;
    string message = string.Format(
@"例外が{0}で発生。プログラムを継続しますか?
エラーメッセージ:{1}",
                              errorMember, errorMessage);
    MessageBoxResult result
      = MessageBox.Show(message, "DispatcherUnhandledException",
                        MessageBoxButton.YesNo, MessageBoxImage.Warning);
    if(result == MessageBoxResult.Yes)
      e.Handled = true;
  }
}
Class Application
  Public Sub New()
    ' UIスレッドで実行されているコードで処理されなかったら発生する(.NET 3.0より)
    AddHandler Me.DispatcherUnhandledException,
      AddressOf App_DispatcherUnhandledException
  End Sub

  Private Sub App_DispatcherUnhandledException(
              sender As Object,
              e As System.Windows.Threading.DispatcherUnhandledExceptionEventArgs)

    Dim errorMember As String = e.Exception.TargetSite.Name
    Dim errorMessage As String = e.Exception.Message
    Dim message As String = String.Format(
"例外が{0}で発生。プログラムを継続しますか?" + vbCrLf _
+ "エラーメッセージ:{1}",
                              errorMember, errorMessage)
    Dim result As MessageBoxResult _
      = MessageBox.Show(message, "DispatcherUnhandledException",
                          MessageBoxButton.YesNo, MessageBoxImage.Warning)
    If (result = MessageBoxResult.Yes) Then
      e.Handled = True
    End If
  End Sub
End Class

UnobservedTaskException

public partial class App : Application
{
  public App()
  {
    // バックグラウンドタスク内で処理されなかったら発生する(.NET 4.0より)
    TaskScheduler.UnobservedTaskException
      += TaskScheduler_UnobservedTaskException;
  }

  private void TaskScheduler_UnobservedTaskException(
                  object sender,
                  UnobservedTaskExceptionEventArgs e)
  {
    string errorMember = e.Exception.InnerException.TargetSite.Name;
    string errorMessage = e.Exception.InnerException.Message;
    string message = string.Format(
@"例外がバックグラウンドタスクの{0}で発生。プログラムを継続しますか?
エラーメッセージ:{1}",
                        errorMember, errorMessage);
    MessageBoxResult result
      = MessageBox.Show(message, "UnobservedTaskException",
                        MessageBoxButton.YesNo, MessageBoxImage.Warning);
    if (result == MessageBoxResult.Yes)
      e.SetObserved();
  }
}

因みに

PowerShellイベントハンドラでは、$_に何かが入っている。

参考

C#, VB http://www.atmarkit.co.jp/ait/spv/1512/16/news026.html

C# http://blog.jhashimoto.net/entry/20101212/1292138123

Technet

https://technet.microsoft.com/de-de/subscriptions/system.windows.application.dispatcherunhandledexception(v=vs.85)

sample

http://thinkami.hatenablog.com/entry/2014/09/04/061854

Code Project

http://www.codeproject.com/Articles/90866/Unhandled-Exception-Handler-For-WPF-Applications