3

現在AppDomain.CurrentDomain.UnhandledException、アプリケーションがクラッシュしたときにスタック トレースをメールで送信するハンドラーがあります。これはほとんどの部分で正常に機能していますが、MVVM ライト ビューモデルで例外が発生した場合、スタック トレースはやや不可解で、どこで発生しているかがわかりません。ビューモデルを try catch ステートメントでラップして、より有用な情報を例外に挿入してから再スローする簡単な方法はありますか?

以下は、スタック トレースの例です。

   System.RuntimeMethodHandle.InvokeMethod (オブジェクト ターゲット、オブジェクト [] 引数、署名 sig、ブール コンストラクター) で
   System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal (オブジェクト obj、オブジェクト [] パラメーター、オブジェクト [] 引数) で
   System.Reflection.RuntimeMethodInfo.Invoke (オブジェクト obj、BindingFlags invokeAttr、バインダー バインダー、オブジェクト [] パラメーター、CultureInfo カルチャ) で
   System.Reflection.MethodBase.Invoke (オブジェクト obj、オブジェクト [] パラメーター) で
   GalaSoft.MvvmLight.Helpers.WeakAction.Execute() で d:\GalaSoft\mydotnet\MvvmLight\Source\GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET35)\Helpers\WeakAction.cs:line 269
   GalaSoft.MvvmLight.Command.RelayCommand.Execute(オブジェクト パラメータ) in d:\GalaSoft\mydotnet\MvvmLight\Source\GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET35)\Command\RelayCommand.cs:167 行目
   MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource (ICommandSource commandSource、ブール値の userInitiated) で
   System.Windows.Controls.Primitives.ButtonBase.OnClick() で
   System.Windows.Controls.Button.OnClick() で
   System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp (MouseButtonEventArgs e) で
   System.Windows.UIElement.OnMouseLeftButtonUpThunk (オブジェクトの送信者、MouseButtonEventArgs e) で
   System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler (デリゲート genericHandler、オブジェクト genericTarget) で
   System.Windows.RoutedEventArgs.InvokeHandler (デリゲート ハンドラー、オブジェクト ターゲット) で
   System.Windows.RoutedEventHandlerInfo.InvokeHandler (オブジェクト ターゲット、RoutedEventArgs、routedEventArgs) で
   System.Windows.EventRoute.InvokeHandlersImpl (オブジェクト ソース、RoutedEventArgs 引数、ブール値の reRaised) で
   System.Windows.UIElement.ReRaiseEventAs (DependencyObject 送信者、RoutedEventArgs 引数、RoutedEvent newEvent) で
   System.Windows.UIElement.OnMouseUpThunk (オブジェクトの送信者、MouseButtonEventArgs e) で
   System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler (デリゲート genericHandler、オブジェクト genericTarget) で
   System.Windows.RoutedEventArgs.InvokeHandler (デリゲート ハンドラー、オブジェクト ターゲット) で
   System.Windows.RoutedEventHandlerInfo.InvokeHandler (オブジェクト ターゲット、RoutedEventArgs、routedEventArgs) で
   System.Windows.EventRoute.InvokeHandlersImpl (オブジェクト ソース、RoutedEventArgs 引数、ブール値の reRaised) で
   System.Windows.UIElement.RaiseEventImpl (DependencyObject 送信者、RoutedEventArgs 引数) で
   System.Windows.UIElement.RaiseTrustedEvent (RoutedEventArgs args) で
   System.Windows.UIElement.RaiseEvent で (RoutedEventArgs 引数、信頼できるブール値)
   System.Windows.Input.InputManager.ProcessStagingArea() で
   System.Windows.Input.InputManager.ProcessInput (InputEventArgs 入力) で
   System.Windows.Input.InputProviderSite.ReportInput (InputReport inputReport) で
   System.Windows.Interop.HwndMouseInputProvider.ReportInput (IntPtr hwnd、InputMode モード、Int32 タイムスタンプ、RawMouseActions アクション、Int32 x、Int32 y、Int32 ホイール) で
   System.Windows.Interop.HwndMouseInputProvider.FilterMessage (IntPtr hwnd、WindowMessage msg、IntPtr wParam、IntPtr lParam、ブール値 & 処理) で
   System.Windows.Interop.HwndSource.InputFilterMessage (IntPtr hwnd、Int32 msg、IntPtr wParam、IntPtr lParam、ブール値 & 処理) で
   MS.Win32.HwndWrapper.WndProc (IntPtr hwnd、Int32 msg、IntPtr wParam、IntPtr lParam、ブール値 & 処理) で
   MS.Win32.HwndSubclass.DispatcherCallbackOperation (オブジェクト o) で
   System.Windows.Threading.ExceptionWrapper.InternalRealCall (デリゲート コールバック、オブジェクト引数、Int32 numArgs) で
   MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen (オブジェクト ソース、デリゲート メソッド、オブジェクト引数、Int32 numArgs、デリゲート catchHandler) で
   System.Windows.Threading.Dispatcher.LegacyInvokeImpl (DispatcherPriority 優先度、TimeSpan タイムアウト、デリゲート メソッド、オブジェクト引数、Int32 numArgs) で
   MS.Win32.HwndSubclass.SubclassWndProc (IntPtr hwnd、Int32 メッセージ、IntPtr wParam、IntPtr lParam) で
   MS.Win32.UnsafeNativeMethods.DispatchMessage (MSG& メッセージ) で
   System.Windows.Threading.Dispatcher.PushFrameImpl (DispatcherFrame フレーム) で
   System.Windows.Threading.Dispatcher.PushFrame (DispatcherFrame フレーム) で
   System.Windows.Threading.Dispatcher.Run() で
   System.Windows.Application.RunDispatcher (オブジェクトは無視) で
   System.Windows.Application.RunInternal (ウィンドウ ウィンドウ) で
   System.Windows.Application.Run (ウィンドウ ウィンドウ) で
   System.Windows.Application.Run() で
   c:|my computer\my projectname\obj\x86\Debug\App.g.cs:line 0 の MyApplication.App.Main() で
   System.AppDomain._nExecuteAssembly (RuntimeAssembly アセンブリ、文字列 [] 引数) で
   System.AppDomain.ExecuteAssembly (文字列 assemblyFile、証拠 assemblySecurity、文字列 [] 引数) で
   Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() で
   System.Threading.ThreadHelper.ThreadStart_Context (オブジェクトの状態) で
   System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext、ContextCallback コールバック、オブジェクトの状態、ブール値の preserveSyncCtx) で
   System.Threading.ExecutionContext.Run (ExecutionContext executionContext、ContextCallback コールバック、オブジェクトの状態、ブール値の preserveSyncCtx) で
   System.Threading.ExecutionContext.Run (ExecutionContext executionContext、ContextCallback コールバック、オブジェクトの状態) で
   System.Threading.ThreadHelper.ThreadStart() で

これは、ボタンをバインドできるようにNotImplementedException、にラップされたビューモデルのメソッドの が原因でした。RelayCommandメソッドの名前またはビューモデルの名前を示すものは何もわかりません。

4

2 に答える 2

6

InnerExceptionプロパティに詳細情報が必要です。

私が間違っていなければ、あなたの主な例外は typeTargetInvocationExceptionです。これをアンラップする小さなメソッドを書くことができます:

public Exception Unwrap(TargetInvocationException root)
{
    if(root.InnerException == null)
        return root;
    var innerException = root.InnerException as TargetInvocationException;
    if(innerException == null)
        return root.InnerException;

    return Unwrap(innerException);
}

TargetInvocationException多くの場合、実際の例外がそれらの3つまたは4つの下に埋もれている複数のレベルがあるため、この方法は役立ちます。

于 2013-10-25T15:16:16.447 に答える
0

すでにイベントを処理している場合AppDomain.CurrentDomain.UnhandledException、そのハンドラーに情報を追加できませんか?:

public void MainWindow_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    Exception exception = (Exception)e.ExceptionObject;
    if (exception.TargetSite.Module.ToString() == "nameOfViewModelAssembly.dll")
    {
        if (exception.StackTrace.Contains(nameOfSomeViewModel))
        {
            throw new Exception("Problem in nameOfSomeViewModel", exception);
        }
        else if (exception.StackTrace.Contains(nameOfOtherViewModel))
        {
            throw new Exception("Problem in nameOfOtherViewModel", exception);
        }
    }
}

もちろん、多くのビュー モデルがある場合、これは非常に大きくなる可能性がありますが、これを行うためのより効率的な方法を見つけることができると確信しています。

于 2013-10-25T14:53:26.577 に答える