19 using System.Collections.Generic;
22 using System.Text.RegularExpressions;
24 using System.Collections.Specialized;
25 using Microsoft.Win32;
38 #region Public properties 46 OnPropertyChanged(
"User");
52 get {
return _email; }
56 OnPropertyChanged(
"Email");
57 OnPropertyChanged(
"IsCcUserEnabled");
63 get {
return _ccUser; }
67 OnPropertyChanged(
"CcUser");
71 public bool IsCcUserEnabled
76 return !String.IsNullOrEmpty(Email);
89 OnPropertyChanged(
"Comment");
93 public string Exception {
get;
private set; }
94 public string Message {
get;
private set; }
95 public string InnerException {
get;
private set; }
96 public string InnerMessage {
get;
private set; }
98 public bool HasInnerException
102 return !String.IsNullOrEmpty(InnerException);
106 public string StackTrace {
get;
private set; }
112 return Environment.OSVersion.VersionString;
120 return Environment.Version.ToString();
124 public string VstoRuntime
128 if (String.IsNullOrEmpty(_vstoRuntime))
130 string suffix = String.Empty;
131 RegistryKey hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
132 RegistryKey v4 = hive.OpenSubKey(
@"Software\Microsoft\VSTO Runtime Setup\V4");
135 v4 = hive.OpenSubKey(
@"Software\Microsoft\VSTO Runtime Setup\V4R");
140 _vstoRuntime = v4.GetValue(
"Version") as string;
142 if (String.IsNullOrEmpty(_vstoRuntime))
144 _vstoRuntime =
"(n/a)";
148 _vstoRuntime += suffix;
155 public string ProcessBitness
159 return Environment.Is64BitProcess ?
"64-bit" :
"32-bit";
163 public string OSBitness
167 return Environment.Is64BitOperatingSystem ?
"64-bit" :
"32-bit";
171 public string ReportID {
get;
private set; }
173 public string IssueUrl {
get;
private set; }
175 public string BovenderFramework
183 public bool IsClickOnceDeployed
187 return System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed;
199 if (_submitReportCommand == null)
202 (param) => DoSubmitReport(),
203 (param) => CanSubmitReport()
206 return _submitReportCommand;
214 if (_viewDetailsCommand == null)
217 (param) => ViewDetailsMessage.Send(
222 return _viewDetailsCommand;
229 if (_clearFormCommand == null) {
231 (param) => DoClearForm(),
232 (param) => CanClearForm()
235 return _clearFormCommand;
244 if (_navigateIssueUrlCommand == null)
247 (param) => DoNavigateIssueUrl());
249 return _navigateIssueUrlCommand;
254 #region MVVM messages 263 if (_viewDetailsMessage == null)
267 return _viewDetailsMessage;
279 if (_submitReportMessage == null)
283 return _submitReportMessage;
301 string devPath = DevPath();
302 if (!String.IsNullOrWhiteSpace(devPath))
304 this.Exception = Regex.Replace(e.ToString(), devPath, String.Empty);
305 if (!String.IsNullOrEmpty(e.StackTrace))
307 StackTrace = Regex.Replace(e.StackTrace, devPath, String.Empty);
311 StackTrace = String.Empty;
315 if (e.InnerException != null)
317 if (!String.IsNullOrWhiteSpace(devPath))
319 InnerException = Regex.Replace(e.InnerException.ToString(), devPath, String.Empty);
321 InnerMessage = e.InnerException.Message;
329 User = UserSettings.User;
330 Email = UserSettings.Email;
331 CcUser = UserSettings.CcUserOnExceptionReport;
336 #region Abstract methods 342 protected abstract Uri GetPostUri();
350 protected override void DoCloseView()
352 UserSettings.User = User;
353 UserSettings.Email = Email;
354 UserSettings.CcUserOnExceptionReport = CcUser;
360 #region Private methods 362 private void webClient_UploadValuesCompleted(
object sender, UploadValuesCompletedEventArgs e)
365 SubmissionProcessMessageContent.IsIndeterminate =
false;
366 SubmissionProcessMessageContent.WasSuccessful =
false;
367 Logger.Info(
"Exception submission completed...");
370 SubmissionProcessMessageContent.WasCancelled =
false;
373 string result = null;
376 result = Encoding.UTF8.GetString(e.Result);
379 Match m = Regex.Match(result,
380 @"{\s*""ReportId"":\s*""(?<reportid>[^""]+)"",\s*""IssueUrl"":\s*""(?<issueurl>[^""]+)""\s*}");
381 if (m.Success && m.Groups[
"reportid"].Value == ReportID)
383 IssueUrl = m.Groups[
"issueurl"].Value;
384 Logger.Info(
"issueUrl: {0}", IssueUrl);
385 SubmissionProcessMessageContent.WasSuccessful =
true;
391 "Received an unexpected return value from the web service (should be report ID {0}).",
399 Logger.Fatal(
"... but response cannot be interpreted!");
401 Logger.Fatal(
"Response: {0}", result);
403 "Exception submission failed", ex);
408 Logger.Warn(
"... with network error:");
409 Logger.Warn(e.Error);
410 SubmissionProcessMessageContent.Exception = e.Error;
415 Logger.Info(
"... was cancelled.");
416 SubmissionProcessMessageContent.WasCancelled =
true;
418 SubmissionProcessMessageContent.Processing =
false;
420 SubmissionProcessMessageContent.CompletedMessage.Send(SubmissionProcessMessageContent);
423 private void CancelSubmission()
425 if (_webClient != null)
427 _webClient.CancelAsync();
433 #region Protected methods 435 protected virtual void DoSubmitReport()
437 Logger.Info(
"Submitting exception report");
438 SubmissionProcessMessageContent.CancelProcess =
new Action(CancelSubmission);
439 SubmissionProcessMessageContent.Processing =
true;
440 _webClient =
new WebClient();
441 NameValueCollection v = GetPostValues();
442 _webClient.UploadValuesCompleted += webClient_UploadValuesCompleted;
443 _webClient.UploadValuesAsync(GetPostUri(), v);
444 SubmitReportMessage.Send(SubmissionProcessMessageContent);
447 protected virtual bool CanSubmitReport()
449 return ((GetPostUri() != null) && !SubmissionProcessMessageContent.Processing);
452 protected virtual void DoClearForm()
455 Email = String.Empty;
456 Comment = String.Empty;
460 protected virtual bool CanClearForm()
463 String.IsNullOrEmpty(User) &&
464 String.IsNullOrEmpty(Email) &&
465 String.IsNullOrEmpty(Comment)
469 protected virtual void DoNavigateIssueUrl()
471 Logger.Info(
"Navigating to issue URL: {0}", IssueUrl);
472 System.Diagnostics.Process.Start(IssueUrl);
483 NameValueCollection v =
new NameValueCollection(20);
484 v[
"report_id"] = ReportID;
485 v[
"usersName"] = User;
486 v[
"usersMail"] = Email;
487 v[
"ccUser"] = CcUser.ToString();
488 v[
"exception"] = Exception;
490 v[
"comment"] = Comment;
491 v[
"inner_exception"] = InnerException;
492 v[
"inner_message"] = InnerMessage;
493 v[
"stack_trace"] = StackTrace;
494 v[
"process_bitness"] = ProcessBitness;
495 v[
"operating_system"] = OS;
496 v[
"os_bitness"] = OSBitness;
497 v[
"clr_version"] = CLR;
498 v[
"vstor_version"] = VstoRuntime;
499 v[
"bovender_version"] = BovenderFramework;
500 v[
"click_once"] = IsClickOnceDeployed.ToString();
526 #region Protected properties 532 if (_submissionProcessMessageContent == null)
536 new Action(CancelSubmission)
538 _submissionProcessMessageContent.IsIndeterminate =
true;
540 return _submissionProcessMessageContent;
546 #region Private fields 548 private string _user;
549 private string _email;
550 private string _comment;
551 private bool _ccUser;
552 private WebClient _webClient;
560 private string _vstoRuntime;
566 private static NLog.Logger Logger {
get {
return _logger.Value; } }
568 private static readonly Lazy<
NLog.Logger> _logger =
new Lazy<
NLog.Logger>(() =>
NLog.LogManager.GetCurrentClassLogger());
Holds information about percent completion of a process and defines events that occur when the proces...
Message content that holds a reference to a view model.
Command that implements ICommand and accepts delegates that contain the command implementation.
Conveys a message from a view model to a consumer (typically, a view) that has subscribed to the Sent...
Provides easy access to several system properties that are relevant for bug reports.
ExceptionViewModel(Exception e)
Instantiates the class and sets the report ID to the hexadecimal representation of the current ticks ...
Base class for persistent settings; a replacement for the UserSettings.UserSettingsBase system which ...
virtual NameValueCollection GetPostValues()
Returns a collection of key-value pairs of exception context information that will be submitted to th...
static string Sha256Hash(string file)
Computes the Sha256 hash of a given file.
virtual string DevPath()
Returns the path(s) on the development machine that shall be stripped from the file information in th...