public static void ReportUnhandledException(Exception ex)
        {
            // if the user hasn't opted in/out yet, ask them
            if (!ReportCrashes.HasValue)
            {
                var handler = ShouldEnableReporting;
                if (handler != null)
                {
                    ReportCrashes = handler();
                }
            }

            // 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.ToText());
                    writer.WriteElementString("Exception", ex.ToString());

                    writer.WriteEndElement();
                }
                data = stream.ToArray();
            }

            // If crash reporting has not been enabled or disabled yet, just log to disk.
            // Otherwise log to disk only if uploading fails.
            var filename = string.Format("{0}.{1}.crashlog", SystemInformation.SessionUuid, Interlocked.Increment(ref CrashId));

            if (!ReportCrashes.GetValueOrDefault() || !TryUploadReport(filename, data))
            {
                if (!Directory.Exists(CrashLogDirectory))
                {
                    Directory.CreateDirectory(CrashLogDirectory);
                }

                File.WriteAllBytes(CrashLogDirectory.Combine(filename), data);
            }
        }
        public static void ProcessCache()
        {
            int origValue = -1;

            try
            {
                // Ensure only 1 thread at a time attempts to upload cached reports
                origValue = Interlocked.CompareExchange(ref Processing, 1, 0);
                if (origValue != 0)
                {
                    return;
                }

                // Uploading is not enabled, so bail out
                if (!ReportCrashes.GetValueOrDefault())
                {
                    return;
                }

                // Definitely no crash reports if this doesn't exist
                if (!Directory.Exists(CrashLogDirectory))
                {
                    return;
                }

                foreach (var file in Directory.GetFiles(CrashLogDirectory))
                {
                    if (TryUploadReport(file, File.ReadAllBytes(file)))
                    {
                        File.Delete(file);
                    }
                }
            }
            catch (Exception ex)
            {
                LoggingService.LogError("Exception processing cached crashes", ex);
            }
            finally
            {
                if (origValue == 0)
                {
                    Interlocked.CompareExchange(ref Processing, 0, 1);
                }
            }
        }