我目前有一个AppDomain.CurrentDomain.UnhandledException
处理程序,当应用程序崩溃时,它会通过电子邮件向我发送堆栈跟踪。这在大多数情况下工作得很好,但是当我在MVVM光视图模型中得到异常时,堆栈跟踪可能相当神秘,并没有真正告诉我它们在哪里发生。有没有一种简单的方法可以将我的viewmodel包装在try catch语句中,然后我可以在异常中注入一些更有用的信息然后重新抛出它?
以下是堆栈跟踪的示例:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) at GalaSoft.MvvmLight.Helpers.WeakAction.Execute() in d:\GalaSoft\mydotnet\MvvmLight\Source\GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET35)\Helpers\WeakAction.cs:line 269 at GalaSoft.MvvmLight.Command.RelayCommand.Execute(Object parameter) in d:\GalaSoft\mydotnet\MvvmLight\Source\GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET35)\Command\RelayCommand.cs:line 167 at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated) at System.Windows.Controls.Primitives.ButtonBase.OnClick() at System.Windows.Controls.Button.OnClick() at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e) at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e) at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent) at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e) at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args) at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted) at System.Windows.Input.InputManager.ProcessStagingArea() at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input) at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport) at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel) at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.Run() at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at System.Windows.Application.Run() at MyApplication.App.Main() in c:|my computer\my projectname\obj\x86\Debug\App.g.cs:line 0 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()
这是由我的viewmodel中包含在NotImplementedException
中的方法中的RelayCommand
引起的,因此我可以将按钮绑定到它。我无法弄清楚是什么让我知道方法的名称或viewmodel的名称。
答案 0 :(得分:6)
您应该在InnerException
属性中获得更多信息。
如果我没有记错,你的主要例外是TargetInvocationException
类型。你可以写一个小方法来解开这个:
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个真正的例外情况。
答案 1 :(得分: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);
}
}
}
当然,如果您有很多视图模型,这可能会变得非常大,但我相信您可以找到一种更有效的方法来实现这一目标。