CLI tool for running Playbooks
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.6 KiB

1 year ago
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.IO.MemoryMappedFiles;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using System.Windows.Forms;
  9. using System.Text.RegularExpressions;
  10. namespace TrustedUninstaller.Shared
  11. {
  12. public static class DualOut
  13. {
  14. private static TextWriter _current;
  15. static MemoryMappedFile mmf = null;
  16. static MemoryMappedViewAccessor accessor = null;
  17. static int absolutePosition = 0;
  18. static int relativePosition = 0;
  19. private static string logDir = Directory.GetCurrentDirectory() + "\\Logs";
  20. private class OutputWriter : TextWriter
  21. {
  22. public override Encoding Encoding
  23. {
  24. get
  25. {
  26. return _current.Encoding;
  27. }
  28. }
  29. public override void WriteLine(string value)
  30. {
  31. value = Regex.Replace(value, "(?<!\\r)\\n", "\r\n");
  32. _current.WriteLine(value);
  33. if (!WinUtil.IsTrustedInstaller())
  34. {
  35. File.AppendAllText($"{logDir}\\AdminOutput.txt", value + Environment.NewLine);
  36. }
  37. else
  38. {
  39. // Small window size to enforce roll-over for testing.
  40. var windowSize = 2000000;
  41. value += Environment.NewLine;
  42. var bytes = Encoding.UTF8.GetBytes(value);
  43. try
  44. {
  45. accessor = mmf.CreateViewAccessor(absolutePosition, windowSize, MemoryMappedFileAccess.ReadWrite);
  46. if (bytes.Length + relativePosition > windowSize)
  47. {
  48. absolutePosition += relativePosition;
  49. relativePosition = 0;
  50. accessor.Dispose();
  51. accessor = mmf.CreateViewAccessor(absolutePosition, windowSize, MemoryMappedFileAccess.ReadWrite);
  52. }
  53. accessor.WriteArray(relativePosition, bytes, 0, bytes.Length);
  54. relativePosition += bytes.Length;
  55. }
  56. finally
  57. {
  58. if (accessor != null)
  59. accessor.Dispose();
  60. }
  61. File.AppendAllText($"{logDir}\\TIOutput.txt", value + Environment.NewLine);
  62. // Small delay, less far less than a millisecond on most processors
  63. Thread.SpinWait(40000);
  64. }
  65. }
  66. public override void WriteLine()
  67. {
  68. WriteLine("");
  69. }
  70. }
  71. public static void Init()
  72. {
  73. if (!Directory.Exists(logDir))
  74. {
  75. Directory.CreateDirectory(logDir);
  76. }
  77. if (WinUtil.IsTrustedInstaller())
  78. {
  79. var i = 0;
  80. while (true)
  81. {
  82. try
  83. {
  84. mmf = MemoryMappedFile.OpenExisting("ImgA");
  85. break;
  86. }
  87. catch (FileNotFoundException)
  88. {
  89. if (i > 300) throw new Exception("Memory file not found.");
  90. Task.Delay(200).Wait();
  91. i++;
  92. }
  93. }
  94. }
  95. _current = Console.Out;
  96. Console.SetOut(new OutputWriter());
  97. }
  98. }
  99. }