ConsoleWindow.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // --------------------------------------------------
  2. // UnityInjector - ConsoleWindow.cs
  3. // Copyright (c) Usagirei 2015 - 2015
  4. // --------------------------------------------------
  5. using System;
  6. using System.Runtime.InteropServices;
  7. namespace UnityInjector.ConsoleUtil
  8. {
  9. internal class ConsoleWindow
  10. {
  11. public static bool IsAttached { get; private set; }
  12. public static IntPtr ConsoleOutHandle;
  13. public static IntPtr OriginalStdoutHandle;
  14. public static void Attach()
  15. {
  16. if (IsAttached)
  17. return;
  18. if (OriginalStdoutHandle == IntPtr.Zero)
  19. OriginalStdoutHandle = GetStdHandle(-11);
  20. // Store Current Window
  21. IntPtr currWnd = GetForegroundWindow();
  22. //Check for existing console before allocating
  23. if (GetConsoleWindow() == IntPtr.Zero)
  24. if (!AllocConsole())
  25. throw new Exception("AllocConsole() failed");
  26. // Restore Foreground
  27. SetForegroundWindow(currWnd);
  28. ConsoleOutHandle = CreateFile("CONOUT$", 0x80000000 | 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero);
  29. BepInEx.ConsoleUtil.Kon.conOut = ConsoleOutHandle;
  30. if (!SetStdHandle(-11, ConsoleOutHandle))
  31. throw new Exception("SetStdHandle() failed");
  32. IsAttached = true;
  33. }
  34. public static string Title
  35. {
  36. set
  37. {
  38. if (!IsAttached)
  39. return;
  40. if (value == null)
  41. {
  42. throw new ArgumentNullException(nameof(value));
  43. }
  44. if (value.Length > 24500)
  45. {
  46. throw new InvalidOperationException("Console title too long");
  47. }
  48. if (!SetConsoleTitle(value))
  49. {
  50. throw new InvalidOperationException("Console title invalid");
  51. }
  52. }
  53. }
  54. public static void Detach()
  55. {
  56. if (!IsAttached)
  57. return;
  58. if (!CloseHandle(ConsoleOutHandle))
  59. throw new Exception("CloseHandle() failed");
  60. ConsoleOutHandle = IntPtr.Zero;
  61. if (!FreeConsole())
  62. throw new Exception("FreeConsole() failed");
  63. if (!SetStdHandle(-11, OriginalStdoutHandle))
  64. throw new Exception("SetStdHandle() failed");
  65. IsAttached = false;
  66. }
  67. [DllImport("user32.dll")]
  68. private static extern IntPtr GetForegroundWindow();
  69. [DllImport("user32.dll")]
  70. [return: MarshalAs(UnmanagedType.Bool)]
  71. private static extern bool SetForegroundWindow(IntPtr hWnd);
  72. [DllImport("kernel32.dll", SetLastError = true)]
  73. private static extern bool AllocConsole();
  74. [DllImport("kernel32.dll")]
  75. private static extern IntPtr GetConsoleWindow();
  76. [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
  77. private static extern bool CloseHandle(IntPtr handle);
  78. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  79. private static extern IntPtr CreateFile(
  80. string fileName,
  81. uint desiredAccess,
  82. int shareMode,
  83. IntPtr securityAttributes,
  84. int creationDisposition,
  85. int flagsAndAttributes,
  86. IntPtr templateFile);
  87. [DllImport("kernel32.dll", SetLastError = false)]
  88. private static extern bool FreeConsole();
  89. [DllImport("kernel32.dll", SetLastError = true)]
  90. private static extern IntPtr GetStdHandle(int nStdHandle);
  91. [DllImport("kernel32.dll", SetLastError = true)]
  92. private static extern bool SetStdHandle(int nStdHandle, IntPtr hConsoleOutput);
  93. [DllImport("kernel32.dll", BestFitMapping = true, CharSet = CharSet.Auto, SetLastError = true)]
  94. private static extern bool SetConsoleTitle(string title);
  95. }
  96. }