PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Startup.cs

https://bitbucket.org/tuldok89/openpdn
C# | 855 lines | 661 code | 145 blank | 49 comment | 39 complexity | 540f56b2a682a388244e049f6de9047c MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using System.Linq;
  10. using PaintDotNet.SystemLayer;
  11. using System;
  12. using System.Collections;
  13. using System.Collections.Generic;
  14. using System.Diagnostics;
  15. using System.Globalization;
  16. using System.IO;
  17. using System.Reflection;
  18. using System.Text;
  19. using System.Threading;
  20. using System.Windows.Forms;
  21. namespace PaintDotNet
  22. {
  23. internal sealed class Startup
  24. {
  25. private static Startup _instance;
  26. private static DateTime _startupTime;
  27. private readonly string[] _args;
  28. private MainForm _mainForm;
  29. private Startup(string[] args)
  30. {
  31. _args = args;
  32. }
  33. /// <summary>
  34. /// Starts a new instance of Paint.NET with the give arguments.
  35. /// </summary>
  36. /// <param name="fileName">The name of the filename to open, or null to start with a blank canvas.</param>
  37. /// <param name="parent"></param>
  38. /// <param name="requireAdmin"></param>
  39. /// <param name="args"></param>
  40. public static void StartNewInstance(IWin32Window parent, bool requireAdmin, string[] args)
  41. {
  42. var allArgsSB = new StringBuilder();
  43. foreach (string arg in args)
  44. {
  45. allArgsSB.Append(' ');
  46. if (arg.IndexOf(' ') != -1)
  47. {
  48. allArgsSB.Append('"');
  49. }
  50. allArgsSB.Append(arg);
  51. if (arg.IndexOf(' ') != -1)
  52. {
  53. allArgsSB.Append('"');
  54. }
  55. }
  56. string allArgs = allArgsSB.Length > 0 ? allArgsSB.ToString(1, allArgsSB.Length - 1) : null;
  57. Shell.Execute(
  58. parent,
  59. Application.ExecutablePath,
  60. allArgs,
  61. requireAdmin ? ExecutePrivilege.RequireAdmin : ExecutePrivilege.AsInvokerOrAsManifest,
  62. ExecuteWaitType.ReturnImmediately);
  63. }
  64. public static void StartNewInstance(IWin32Window parent, string fileName)
  65. {
  66. string arg;
  67. if (!string.IsNullOrEmpty(fileName))
  68. {
  69. arg = "\"" + fileName + "\"";
  70. }
  71. else
  72. {
  73. arg = "";
  74. }
  75. StartNewInstance(parent, false, new[] { arg });
  76. }
  77. private static bool CloseForm(Form form)
  78. {
  79. var openForms = new ArrayList(Application.OpenForms);
  80. if (openForms.IndexOf(form) == -1)
  81. {
  82. return false;
  83. }
  84. form.Close();
  85. var openForms2 = new ArrayList(Application.OpenForms);
  86. return openForms2.IndexOf(form) == -1;
  87. }
  88. public static bool CloseApplication()
  89. {
  90. bool returnVal = true;
  91. var allFormsButMainForm = Application.OpenForms.Cast<Form>().Where(form => form.Modal && !ReferenceEquals(form, _instance._mainForm)).ToList();
  92. if (allFormsButMainForm.Count > 0)
  93. {
  94. // Cannot close application if there are modal dialogs
  95. return false;
  96. }
  97. returnVal = CloseForm(_instance._mainForm);
  98. return returnVal;
  99. }
  100. /// <summary>
  101. /// Checks to make sure certain files are present, and tries to repair the problem.
  102. /// </summary>
  103. /// <returns>
  104. /// true if any repairs had to be made, at which point PDN must be restarted.
  105. /// false otherwise, if everything's okay.
  106. /// </returns>
  107. private static bool CheckForImportantFiles()
  108. {
  109. var requiredFiles =
  110. new[]
  111. {
  112. "FileTypes\\DdsFileType.dll",
  113. "ICSharpCode.SharpZipLib.dll",
  114. "Interop.WIA.dll",
  115. "PaintDotNet.Base.dll",
  116. "PaintDotNet.Core.dll",
  117. "PaintDotNet.Data.dll",
  118. "PaintDotNet.Effects.dll",
  119. "PaintDotNet.Resources.dll",
  120. "PaintDotNet.Strings.3.DE.resources",
  121. "PaintDotNet.Strings.3.ES.resources",
  122. "PaintDotNet.Strings.3.FR.resources",
  123. "PaintDotNet.Strings.3.IT.resources",
  124. "PaintDotNet.Strings.3.JA.resources",
  125. "PaintDotNet.Strings.3.KO.resources",
  126. "PaintDotNet.Strings.3.PT-BR.resources",
  127. "PaintDotNet.Strings.3.resources",
  128. "PaintDotNet.Strings.3.ZH-CN.resources",
  129. "PaintDotNet.StylusReader.dll",
  130. "PaintDotNet.SystemLayer.dll",
  131. "SetupNgen.exe",
  132. "ShellExtension_x64.dll",
  133. "ShellExtension_x86.dll",
  134. "Squish_x64.dll",
  135. "Squish_x86.dll",
  136. "Squish_x86_SSE2.dll",
  137. "UpdateMonitor.exe",
  138. "WiaProxy32.exe"
  139. };
  140. string dirName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  141. List<string> missingFiles = null;
  142. foreach (string requiredFile in requiredFiles)
  143. {
  144. bool missing;
  145. try
  146. {
  147. string pathName = Path.Combine(dirName, requiredFile);
  148. var fileInfo = new FileInfo(pathName);
  149. missing = !fileInfo.Exists;
  150. }
  151. catch (Exception)
  152. {
  153. missing = true;
  154. }
  155. if (!missing) continue;
  156. if (missingFiles == null)
  157. {
  158. missingFiles = new List<string>();
  159. }
  160. missingFiles.Add(requiredFile);
  161. }
  162. if (missingFiles == null)
  163. {
  164. return false;
  165. }
  166. if (Shell.ReplaceMissingFiles(missingFiles.ToArray()))
  167. {
  168. // Everything is repaired and happy.
  169. return true;
  170. }
  171. // Things didn't get fixed. Bail.
  172. Process.GetCurrentProcess().Kill();
  173. return false;
  174. }
  175. public void Start()
  176. {
  177. // Set up unhandled exception handlers
  178. #if DEBUG
  179. // In debug builds we'd prefer to have it dump us into the debugger
  180. #else
  181. AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
  182. Application.ThreadException += ApplicationThreadException;
  183. #endif
  184. // Initialize some misc. Windows Forms settings
  185. Application.SetCompatibleTextRenderingDefault(false);
  186. Application.EnableVisualStyles();
  187. // If any files are missing, try to repair.
  188. // However, support /skipRepairAttempt for when developing in the IDE
  189. // so that we don't needlessly try to repair in that case.
  190. if (_args.Length > 0 &&
  191. string.Compare(_args[0], "/skipRepairAttempt", StringComparison.InvariantCultureIgnoreCase) == 0)
  192. {
  193. // do nothing: we need this so that we can run from IDE/debugger
  194. // without it trying to repair itself all the time
  195. }
  196. else
  197. {
  198. if (CheckForImportantFiles())
  199. {
  200. StartNewInstance(null, false, _args);
  201. return;
  202. }
  203. }
  204. // The rest of the code is put in a separate method so that certain DLL's
  205. // won't get delay loaded until after we try to do repairs.
  206. StartPart2();
  207. }
  208. private void StartPart2()
  209. {
  210. // Set up locale / resource details
  211. string locale = Settings.CurrentUser.GetString(SettingNames.LanguageName, null) ??
  212. Settings.SystemWide.GetString(SettingNames.LanguageName, null);
  213. if (locale != null)
  214. {
  215. try
  216. {
  217. var ci = new CultureInfo(locale, true);
  218. Thread.CurrentThread.CurrentUICulture = ci;
  219. }
  220. catch (Exception)
  221. {
  222. // Don't want bad culture name to crash us
  223. }
  224. }
  225. // Check system requirements
  226. if (!OS.CheckOSRequirement())
  227. {
  228. string message = PdnResources.GetString("Error.OSRequirement");
  229. Utility.ErrorBox(null, message);
  230. return;
  231. }
  232. // Parse command-line arguments
  233. if (_args.Length == 1 &&
  234. _args[0] == Updates.UpdatesOptionsDialog.CommandLineParameter)
  235. {
  236. Updates.UpdatesOptionsDialog.ShowUpdateOptionsDialog(null, false);
  237. }
  238. else
  239. {
  240. var singleInstanceManager = new SingleInstanceManager(InvariantStrings.SingleInstanceMonikerName);
  241. // If this is not the first instance of PDN.exe, then forward the command-line
  242. // parameters over to the first instance.
  243. if (!singleInstanceManager.IsFirstInstance)
  244. {
  245. singleInstanceManager.FocusFirstInstance();
  246. foreach (string arg in _args)
  247. {
  248. singleInstanceManager.SendInstanceMessage(arg, 30);
  249. }
  250. singleInstanceManager.Dispose();
  251. singleInstanceManager = null;
  252. return;
  253. }
  254. // Create main window
  255. _mainForm = new MainForm(_args)
  256. {
  257. SingleInstanceManager = singleInstanceManager
  258. };
  259. singleInstanceManager = null; // mainForm owns it now
  260. // 3 2 1 go
  261. Application.Run(_mainForm);
  262. try
  263. {
  264. _mainForm.Dispose();
  265. }
  266. catch (Exception)
  267. {
  268. }
  269. _mainForm = null;
  270. }
  271. }
  272. /// <summary>
  273. /// The main entry point for the application.
  274. /// </summary>
  275. [STAThread]
  276. public static int Main(string[] args)
  277. {
  278. _startupTime = DateTime.Now;
  279. #if !DEBUG
  280. try
  281. {
  282. #endif
  283. AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;
  284. _instance = new Startup(args);
  285. _instance.Start();
  286. #if !DEBUG
  287. }
  288. catch (Exception ex)
  289. {
  290. try
  291. {
  292. UnhandledException(ex);
  293. Process.GetCurrentProcess().Kill();
  294. }
  295. catch (Exception)
  296. {
  297. MessageBox.Show(ex.ToString());
  298. Process.GetCurrentProcess().Kill();
  299. }
  300. }
  301. #endif
  302. return 0;
  303. }
  304. private static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
  305. {
  306. // For v3.05, we renamed PdnLib.dll to PaintDotNet.Core.dll. So we should really make
  307. // sure we stay compatible with old plugin DLL's.
  308. const string oldCoreName = "PdnLib";
  309. int index = args.Name.IndexOf(oldCoreName, StringComparison.InvariantCultureIgnoreCase);
  310. Assembly newAssembly = null;
  311. if (index == 0)
  312. {
  313. newAssembly = typeof(ColorBgra).Assembly;
  314. }
  315. return newAssembly;
  316. }
  317. private static void UnhandledException(Exception ex)
  318. {
  319. string dir = Shell.GetVirtualPath(VirtualFolderName.UserDesktop, true);
  320. const string fileName = "pdncrash.log";
  321. string fullName = Path.Combine(dir, fileName);
  322. using (var stream = new StreamWriter(fullName, true))
  323. {
  324. stream.AutoFlush = true;
  325. WriteCrashLog(ex, stream);
  326. }
  327. string errorFormat;
  328. try
  329. {
  330. errorFormat = PdnResources.GetString("Startup.UnhandledError.Format");
  331. }
  332. catch (Exception)
  333. {
  334. errorFormat = InvariantStrings.StartupUnhandledErrorFormatFallback;
  335. }
  336. string errorText = string.Format(errorFormat, fileName);
  337. Utility.ErrorBox(null, errorText);
  338. }
  339. public static string GetCrashLogHeader()
  340. {
  341. var headerSB = new StringBuilder();
  342. var headerSW = new StringWriter(headerSB);
  343. WriteCrashLog(null, headerSW);
  344. return headerSB.ToString();
  345. }
  346. private static void WriteCrashLog(Exception ex, TextWriter stream)
  347. {
  348. string headerFormat;
  349. try
  350. {
  351. headerFormat = PdnResources.GetString("CrashLog.HeaderText.Format");
  352. }
  353. catch (Exception ex13)
  354. {
  355. headerFormat =
  356. InvariantStrings.CrashLogHeaderTextFormatFallback +
  357. ", --- Exception while calling PdnResources.GetString(\"CrashLog.HeaderText.Format\"): " +
  358. ex13 +
  359. Environment.NewLine;
  360. }
  361. string header;
  362. try
  363. {
  364. header = string.Format(headerFormat, InvariantStrings.CrashlogEmail);
  365. }
  366. catch
  367. {
  368. header = string.Empty;
  369. }
  370. stream.WriteLine(header);
  371. const string noInfoString = "err";
  372. string fullAppName = noInfoString;
  373. string timeOfCrash = noInfoString;
  374. string appUptime = noInfoString;
  375. string osVersion = noInfoString;
  376. string osRevision = noInfoString;
  377. string osType = noInfoString;
  378. string processorNativeArchitecture = noInfoString;
  379. string clrVersion = noInfoString;
  380. string fxInventory = noInfoString;
  381. string processorArchitecture = noInfoString;
  382. string cpuName = noInfoString;
  383. string cpuCount = noInfoString;
  384. string cpuSpeed = noInfoString;
  385. string cpuFeatures = noInfoString;
  386. string totalPhysicalBytes = noInfoString;
  387. string dpiInfo = noInfoString;
  388. string localeName = noInfoString;
  389. string inkInfo = noInfoString;
  390. string updaterInfo = noInfoString;
  391. string featuresInfo = noInfoString;
  392. string assembliesInfo = noInfoString;
  393. try
  394. {
  395. try
  396. {
  397. fullAppName = PdnInfo.GetFullAppName();
  398. }
  399. catch (Exception ex1)
  400. {
  401. fullAppName = Application.ProductVersion + ", --- Exception while calling PdnInfo.GetFullAppName(): " + ex1 + Environment.NewLine;
  402. }
  403. try
  404. {
  405. timeOfCrash = DateTime.Now.ToString();
  406. }
  407. catch (Exception ex2)
  408. {
  409. timeOfCrash = "--- Exception while populating timeOfCrash: " + ex2 + Environment.NewLine;
  410. }
  411. try
  412. {
  413. appUptime = (DateTime.Now - _startupTime).ToString();
  414. }
  415. catch (Exception ex13)
  416. {
  417. appUptime = "--- Exception while populating appUptime: " + ex13 + Environment.NewLine;
  418. }
  419. try
  420. {
  421. osVersion = Environment.OSVersion.Version.ToString();
  422. }
  423. catch (Exception ex3)
  424. {
  425. osVersion = "--- Exception while populating osVersion: " + ex3 + Environment.NewLine;
  426. }
  427. try
  428. {
  429. osRevision = OS.Revision;
  430. }
  431. catch (Exception ex4)
  432. {
  433. osRevision = "--- Exception while populating osRevision: " + ex4 + Environment.NewLine;
  434. }
  435. try
  436. {
  437. osType = OS.Type.ToString();
  438. }
  439. catch (Exception ex5)
  440. {
  441. osType = "--- Exception while populating osType: " + ex5 + Environment.NewLine;
  442. }
  443. try
  444. {
  445. processorNativeArchitecture = Processor.NativeArchitecture.ToString().ToLower();
  446. }
  447. catch (Exception ex6)
  448. {
  449. processorNativeArchitecture = "--- Exception while populating processorNativeArchitecture: " + ex6 + Environment.NewLine;
  450. }
  451. try
  452. {
  453. clrVersion = Environment.Version.ToString();
  454. }
  455. catch (Exception ex7)
  456. {
  457. clrVersion = "--- Exception while populating clrVersion: " + ex7 + Environment.NewLine;
  458. }
  459. try
  460. {
  461. fxInventory =
  462. (OS.IsDotNetVersionInstalled(2, 0, 0, false) ? "2.0 " : "") +
  463. (OS.IsDotNetVersionInstalled(2, 0, 1, false) ? "2.0SP1 " : "") +
  464. (OS.IsDotNetVersionInstalled(2, 0, 2, false) ? "2.0SP2 " : "") +
  465. (OS.IsDotNetVersionInstalled(3, 0, 0, false) ? "3.0 " : "") +
  466. (OS.IsDotNetVersionInstalled(3, 0, 1, false) ? "3.0SP1 " : "") +
  467. (OS.IsDotNetVersionInstalled(3, 0, 2, false) ? "3.0SP2 " : "") +
  468. (OS.IsDotNetVersionInstalled(3, 5, 0, false) ? "3.5 " : "") +
  469. (OS.IsDotNetVersionInstalled(3, 5, 1, false) ? "3.5SP1 " : "") +
  470. (OS.IsDotNetVersionInstalled(3, 5, 1, true) ? "3.5SP1_Client " : "") +
  471. (OS.IsDotNetVersionInstalled(3, 5, 2, false) ? "3.5SP2 " : "") +
  472. (OS.IsDotNetVersionInstalled(4, 0, 0, false) ? "4.0 " : "") +
  473. (OS.IsDotNetVersionInstalled(4, 0, 1, false) ? "4.0SP1 " : "") +
  474. (OS.IsDotNetVersionInstalled(4, 0, 2, false) ? "4.0SP2 " : "")
  475. .Trim();
  476. }
  477. catch (Exception ex30)
  478. {
  479. fxInventory = "--- Exception while populating fxInventory: " + ex30 + Environment.NewLine;
  480. }
  481. try
  482. {
  483. processorArchitecture = Processor.Architecture.ToString().ToLower();
  484. }
  485. catch (Exception ex8)
  486. {
  487. processorArchitecture = "--- Exception while populating processorArchitecture: " + ex8 + Environment.NewLine;
  488. }
  489. try
  490. {
  491. cpuName = Processor.CpuName;
  492. }
  493. catch (Exception ex9)
  494. {
  495. cpuName = "--- Exception while populating cpuName: " + ex9 + Environment.NewLine;
  496. }
  497. try
  498. {
  499. cpuCount = Processor.LogicalCpuCount + "x";
  500. }
  501. catch (Exception ex10)
  502. {
  503. cpuCount = "--- Exception while populating cpuCount: " + ex10 + Environment.NewLine;
  504. }
  505. try
  506. {
  507. cpuSpeed = "@ ~" + Processor.ApproximateSpeedMhz + "MHz";
  508. }
  509. catch (Exception ex16)
  510. {
  511. cpuSpeed = "--- Exception while populating cpuSpeed: " + ex16 + Environment.NewLine;
  512. }
  513. try
  514. {
  515. cpuFeatures = string.Empty;
  516. string[] featureNames = Enum.GetNames(typeof(ProcessorFeature));
  517. bool firstFeature = true;
  518. foreach (string featureName in from featureName in featureNames
  519. let feature = (ProcessorFeature) Enum.Parse(typeof (ProcessorFeature), featureName)
  520. where Processor.IsFeaturePresent(feature)
  521. select featureName)
  522. {
  523. if (firstFeature)
  524. {
  525. cpuFeatures = "(";
  526. firstFeature = false;
  527. }
  528. else
  529. {
  530. cpuFeatures += ", ";
  531. }
  532. cpuFeatures += featureName;
  533. }
  534. if (cpuFeatures.Length > 0)
  535. {
  536. cpuFeatures += ")";
  537. }
  538. }
  539. catch (Exception ex17)
  540. {
  541. cpuFeatures = "--- Exception while populating cpuFeatures: " + ex17 + Environment.NewLine;
  542. }
  543. try
  544. {
  545. totalPhysicalBytes = ((Memory.TotalPhysicalBytes / 1024) / 1024) + " MB";
  546. }
  547. catch (Exception ex11)
  548. {
  549. totalPhysicalBytes = "--- Exception while populating totalPhysicalBytes: " + ex11 + Environment.NewLine;
  550. }
  551. try
  552. {
  553. float xScale;
  554. try
  555. {
  556. xScale = UI.GetXScaleFactor();
  557. }
  558. catch (Exception)
  559. {
  560. using (var c = new Control())
  561. {
  562. UI.InitScaling(c);
  563. xScale = UI.GetXScaleFactor();
  564. }
  565. }
  566. dpiInfo = string.Format("{0} dpi ({1}x scale)", (96.0f * xScale).ToString("F2"), xScale.ToString("F2"));
  567. }
  568. catch (Exception ex19)
  569. {
  570. dpiInfo = "--- Exception while populating dpiInfo: " + ex19 + Environment.NewLine;
  571. }
  572. try
  573. {
  574. localeName =
  575. "pdnr.c: " + PdnResources.Culture.Name +
  576. ", hklm: " + Settings.SystemWide.GetString(SettingNames.LanguageName, "n/a") +
  577. ", hkcu: " + Settings.CurrentUser.GetString(SettingNames.LanguageName, "n/a") +
  578. ", cc: " + CultureInfo.CurrentCulture.Name +
  579. ", cuic: " + CultureInfo.CurrentUICulture.Name;
  580. }
  581. catch (Exception ex14)
  582. {
  583. localeName = "--- Exception while populating localeName: " + ex14 + Environment.NewLine;
  584. }
  585. try
  586. {
  587. inkInfo = Ink.IsAvailable() ? "yes" : "no";
  588. }
  589. catch (Exception ex15)
  590. {
  591. inkInfo = "--- Exception while populating inkInfo: " + ex15 + Environment.NewLine;
  592. }
  593. try
  594. {
  595. string autoCheckForUpdates = Settings.SystemWide.GetString(SettingNames.AutoCheckForUpdates, noInfoString);
  596. string lastUpdateCheckTimeInfo;
  597. try
  598. {
  599. string lastUpdateCheckTimeString = Settings.CurrentUser.Get(SettingNames.LastUpdateCheckTimeTicks);
  600. long lastUpdateCheckTimeTicks = long.Parse(lastUpdateCheckTimeString);
  601. var lastUpdateCheckTime = new DateTime(lastUpdateCheckTimeTicks);
  602. lastUpdateCheckTimeInfo = lastUpdateCheckTime.ToShortDateString();
  603. }
  604. catch (Exception)
  605. {
  606. lastUpdateCheckTimeInfo = noInfoString;
  607. }
  608. updaterInfo = string.Format(
  609. "{0}, {1}",
  610. (autoCheckForUpdates == "1") ? "true" : (autoCheckForUpdates == "0" ? "false" : (autoCheckForUpdates ?? "null")),
  611. lastUpdateCheckTimeInfo);
  612. }
  613. catch (Exception ex17)
  614. {
  615. updaterInfo = "--- Exception while populating updaterInfo: " + ex17 + Environment.NewLine;
  616. }
  617. try
  618. {
  619. var featureSB = new StringBuilder();
  620. IEnumerable<string> featureList = Tracing.GetLoggedFeatures();
  621. bool first = true;
  622. foreach (string feature in featureList)
  623. {
  624. if (!first)
  625. {
  626. featureSB.Append(", ");
  627. }
  628. featureSB.Append(feature);
  629. first = false;
  630. }
  631. featuresInfo = featureSB.ToString();
  632. }
  633. catch (Exception ex18)
  634. {
  635. featuresInfo = "--- Exception while populating featuresInfo: " + ex18 + Environment.NewLine;
  636. }
  637. try
  638. {
  639. var assembliesInfoSB = new StringBuilder();
  640. Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
  641. foreach (Assembly assembly in loadedAssemblies)
  642. {
  643. assembliesInfoSB.AppendFormat("{0} {1} @ {2}", Environment.NewLine, assembly.FullName, assembly.Location);
  644. }
  645. assembliesInfo = assembliesInfoSB.ToString();
  646. }
  647. catch (Exception ex16)
  648. {
  649. assembliesInfo = "--- Exception while populating assembliesInfo: " + ex16 + Environment.NewLine;
  650. }
  651. }
  652. catch (Exception ex12)
  653. {
  654. stream.WriteLine("Exception while gathering app and system info: " + ex12);
  655. }
  656. stream.WriteLine("Application version: " + fullAppName);
  657. stream.WriteLine("Time of crash: " + timeOfCrash);
  658. stream.WriteLine("Application uptime: " + appUptime);
  659. stream.WriteLine("OS Version: " + osVersion + (string.IsNullOrEmpty(osRevision) ? "" : (" " + osRevision)) + " " + osType + " " + processorNativeArchitecture);
  660. stream.WriteLine(".NET version: CLR " + clrVersion + " " + processorArchitecture + ", FX " + fxInventory);
  661. stream.WriteLine("Processor: " + cpuCount + " \"" + cpuName + "\" " + cpuSpeed + " " + cpuFeatures);
  662. stream.WriteLine("Physical memory: " + totalPhysicalBytes);
  663. stream.WriteLine("UI DPI: " + dpiInfo);
  664. stream.WriteLine("Tablet PC: " + inkInfo);
  665. stream.WriteLine("Updates: " + updaterInfo);
  666. stream.WriteLine("Locale: " + localeName);
  667. stream.WriteLine("Features log: " + featuresInfo);
  668. stream.WriteLine("Loaded assemblies: " + assembliesInfo);
  669. stream.WriteLine();
  670. stream.WriteLine("Exception details:");
  671. if (ex == null)
  672. {
  673. stream.WriteLine("(null)");
  674. }
  675. else
  676. {
  677. stream.WriteLine(ex.ToString());
  678. // Determine if there is any 'secondary' exception to report
  679. Exception[] otherEx = null;
  680. if (ex is ReflectionTypeLoadException)
  681. {
  682. otherEx = ((ReflectionTypeLoadException)ex).LoaderExceptions;
  683. }
  684. if (otherEx != null)
  685. {
  686. foreach (Exception t in otherEx)
  687. {
  688. stream.WriteLine();
  689. stream.WriteLine("Secondary exception details:");
  690. stream.WriteLine(t == null ? "(null)" : t.ToString());
  691. }
  692. }
  693. }
  694. stream.WriteLine("------------------------------------------------------------------------------");
  695. stream.Flush();
  696. }
  697. private static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
  698. {
  699. UnhandledException((Exception)e.ExceptionObject);
  700. Process.GetCurrentProcess().Kill();
  701. }
  702. private static void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
  703. {
  704. UnhandledException(e.Exception);
  705. Process.GetCurrentProcess().Kill();
  706. }
  707. }
  708. }