internal static void ReportUnhandledException(Exception ex, bool willShutDown, bool silently, string tag) { var tags = new List <string> { tag }; if (reporting) { return; } reporting = true; try { var oldReportCrashes = ReportCrashes; if (UnhandledErrorOccured != null && !silently) { ReportCrashes = UnhandledErrorOccured(ReportCrashes, ex, willShutDown); } // If crash reporting has been explicitly disabled, disregard this crash if (ReportCrashes.HasValue && !ReportCrashes.Value) { return; } byte[] data; using (var stream = new MemoryStream()) { using (var writer = System.Xml.XmlWriter.Create(stream)) { writer.WriteStartElement("CrashLog"); writer.WriteAttributeString("version", ServiceVersion); writer.WriteElementString("SystemInformation", SystemInformation.GetTextDescription()); writer.WriteElementString("Exception", ex.ToString()); writer.WriteEndElement(); } data = stream.ToArray(); } var customData = new Hashtable(); customData["SystemInformation"] = SystemInformation.GetTextDescription(); if (raygunClient != null) { ThreadPool.QueueUserWorkItem(delegate { raygunClient.Send(ex, tags, customData, BuildInfo.Version); }); } // Log to disk only if uploading fails. var filename = string.Format("{0}.{1}.{2}.crashlog", DateTime.UtcNow.ToString("yyyy-MM-dd__HH-mm-ss"), SystemInformation.SessionUuid, Interlocked.Increment(ref CrashId)); ThreadPool.QueueUserWorkItem(delegate { if (!TryUploadReport(filename, data)) { if (!Directory.Exists(CrashLogDirectory)) { Directory.CreateDirectory(CrashLogDirectory); } File.WriteAllBytes(CrashLogDirectory.Combine(filename), data); } }); //ensure we don't lose the setting if (ReportCrashes != oldReportCrashes) { PropertyService.SaveProperties(); } } finally { reporting = false; } }