ConsoleWindow.cs 3.4 KB

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