1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.Activities.Presentation
7 using System.Activities.Presentation.Internal.PropertyEditing;
8 using System.Activities.Presentation.View;
9 using System.Diagnostics;
12 using System.Threading;
14 using System.Windows.Controls;
15 using System.Windows.Input;
16 using System.Globalization;
17 using System.Diagnostics.CodeAnalysis;
19 [Fx.Tag.XamlVisible(false)]
20 internal static class ErrorReporting
22 private static WeakReference activeDesignerViewReference;
24 internal static DesignerView ActiveDesignerView
28 if (activeDesignerViewReference != null)
30 return activeDesignerViewReference.Target as DesignerView;
39 activeDesignerViewReference = null;
43 activeDesignerViewReference = new WeakReference(value);
48 public static void ShowErrorMessage(string message)
50 ShowErrorMessage(message, false);
53 public static void ShowAlertMessage(string message)
55 ShowAlertMessage(message, false);
58 public static void ShowErrorMessage(string message, string details)
60 if (string.IsNullOrEmpty(details))
62 ShowErrorMessage(message);
66 ShowErrorMessage(string.Format(CultureInfo.CurrentUICulture, "{0}\n\n\"{1}\"", message, details));
70 public static void ShowErrorMessage(string message, bool includeStackTrace)
72 string stackTrace = null;
73 if (includeStackTrace)
75 //generate stack trace
76 stackTrace = new StackTrace().ToString();
77 //remove top frame from the trace (which is a call to ShowErrorMessage)
78 stackTrace = stackTrace.Remove(0, stackTrace.IndexOf(Environment.NewLine, StringComparison.Ordinal) + 1);
80 ShowMessageBox(message, MessageBoxImage.Error, stackTrace);
83 public static void ShowAlertMessage(string message, bool includeStackTrace)
85 string stackTrace = null;
86 if (includeStackTrace)
88 //generate stack trace
89 stackTrace = new StackTrace().ToString();
90 //remove top frame from the trace (which is a call to ShowAlertMessage)
91 stackTrace = stackTrace.Remove(0, stackTrace.IndexOf(Environment.NewLine, StringComparison.Ordinal) + 1);
93 ShowMessageBox(message, MessageBoxImage.Warning, stackTrace);
96 public static void ShowErrorMessage(Exception err)
100 ShowMessageBox(string.Format(CultureInfo.InvariantCulture, "{0}:\r\n{1}", err.GetType().Name, err.Message), MessageBoxImage.Error, err.StackTrace);
104 static void ShowMessageBox(string message, MessageBoxImage icon, string stackTrace)
107 string iconName = icon == MessageBoxImage.Error ? "TextBoxErrorIcon" :
108 icon == MessageBoxImage.Warning ? "WarningValidationIcon" : string.Empty;
111 var dlg = new ErrorDialog()
113 ErrorDescription = message ?? "<null>",
114 Icon = EditorResources.GetIcons()[iconName],
115 StackTrace = stackTrace,
116 StackTraceVisibility = string.IsNullOrEmpty(stackTrace) ? Visibility.Collapsed : Visibility.Visible,
117 Context = null != ActiveDesignerView ? ActiveDesignerView.Context : null,
118 Owner = ActiveDesignerView,
124 sealed class ErrorDialog : WorkflowElementDialog
126 public string ErrorDescription { get; set; }
128 public Visibility StackTraceVisibility { get; set; }
130 public string StackTrace { get; set; }
132 [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode,
133 Justification = "This property is accessed by XAML")]
134 public object Icon { get; set; }
136 protected override void OnInitialized(EventArgs e)
138 this.Title = SR.WorkflowDesignerErrorPresenterTitle;
139 this.Content = new ContentPresenter()
141 ContentTemplate = (DataTemplate)EditorResources.GetResources()["ErrorPresenterDialogTemplate"],
145 this.WindowResizeMode = ResizeMode.NoResize;
146 this.WindowSizeToContent = SizeToContent.WidthAndHeight;
147 //handle loaded event
148 this.Loaded += this.OnDialogWindowLoaded;
149 base.OnInitialized(e);
152 void OnDialogWindowLoaded(object s, RoutedEventArgs e)
154 //get the containing window
155 var parentWindow = VisualTreeUtils.FindVisualAncestor<Window>(this);
156 //and handle KeyDown event - in case of Esc, we should close the dialog
157 parentWindow.KeyDown += OnWindowKeyDown;
159 //add Copy command support - when user presses Ctrl+C, copy content of the error into clipboard
160 var copyBinding = new CommandBinding(ApplicationCommands.Copy);
161 copyBinding.PreviewCanExecute += OnCopyCanExecute;
162 copyBinding.Executed += OnCopyExecuted;
163 parentWindow.CommandBindings.Add(copyBinding);
166 void OnWindowKeyDown(object s, KeyEventArgs e)
168 //Esc - close the dialog box
169 if (e.Key == Key.Escape)
171 ((Window)s).DialogResult = false;
176 void OnCopyCanExecute(object s, CanExecuteRoutedEventArgs e)
178 //do not allow text boxes to handle the ApplicationCommand.Copy, i will handle it myself
180 e.ContinueRouting = false;
184 void OnCopyExecuted(object s, ExecutedRoutedEventArgs e)
186 //build a string with detailed error description
187 StringBuilder error = new StringBuilder();
188 error.Append('-', 25);
189 error.Append(Environment.NewLine);
190 error.Append(this.Title);
191 error.Append(Environment.NewLine);
192 error.Append('-', 25);
193 error.Append(Environment.NewLine);
194 error.Append(this.ErrorDescription);
195 error.Append(Environment.NewLine);
196 if (this.StackTraceVisibility == Visibility.Visible)
198 error.Append('-', 25);
199 error.Append(Environment.NewLine);
200 error.Append(this.StackTrace);
201 error.Append(Environment.NewLine);
203 error.Append('-', 25);
204 error.Append(Environment.NewLine);
205 string result = error.ToString();
207 //attempt to set the value into clipboard - according to MSDN - if a call fails, it means some other process is accessing clipboard
209 for (int i = 0; i < 10; ++i)
213 Clipboard.SetText(result);
216 catch (Exception err)