Game.WinConsole
Assembly: Assembly-CSharp
Namespace: Game.Debug
Type: internal static class
Base: System.Object
Summary: This helper class manages a Windows console for the game process. It can attach to the parent process console or allocate a new console and redirects .NET Console streams (Console.Out, Console.Error and Console.In) to the native console handles (CONOUT$, CONIN$). It uses P/Invoke to call kernel32 functions (AllocConsole, AttachConsole, CreateFileW) and creates FileStream wrappers around console handles to set up StreamWriter/StreamReader redirection. This is Windows-only and requires the game to run with permissions that allow calling these Win32 APIs.
Fields
-
private const uint GENERIC_WRITE
This constant (0x40000000) is the Win32 GENERIC_WRITE access mask used when opening CONOUT$. -
private const uint GENERIC_READ
This constant (0x80000000) is the Win32 GENERIC_READ access mask used when opening CONIN$. -
private const uint FILE_SHARE_READ
Win32 FILE_SHARE_READ (0x1) share mode. -
private const uint FILE_SHARE_WRITE
Win32 FILE_SHARE_WRITE (0x2) share mode. -
private const uint OPEN_EXISTING
Win32 OPEN_EXISTING (0x3) creation disposition used for console file names. -
private const uint FILE_ATTRIBUTE_NORMAL
Win32 FILE_ATTRIBUTE_NORMAL (0x80) attribute flag. -
private const uint ERROR_ACCESS_DENIED
Win32 error code for access denied (0x5). Used to check AttachConsole failure reason. -
private const uint ATTACH_PARRENT
Value set to uint.MaxValue (0xFFFFFFFF) used when calling AttachConsole to attach to the parent process console.
Properties
- None. (This is a static helper class and exposes no properties.)
Constructors
- No public or instance constructors.
Because WinConsole is declared static, it cannot be instantiated and does not expose constructors.
Methods
-
public static void Initialize(bool alwaysCreateNewConsole = true)
Initializes a console for the current process. If alwaysCreateNewConsole is true, the method attempts to allocate a new console via AllocConsole(). If false, it first attempts to attach to the parent process console via AttachConsole(ATTACH_PARRENT). If attaching fails for a reason other than access denied, the code will allocate a new console. After a successful attach/alloc, the method calls into InitializeOutStream() to redirect Console.Out and Console.Error. -
private static void InitializeOutStream()
Creates a FileStream for "CONOUT$" and wraps it in a StreamWriter (AutoFlush = true). Then sets Console.SetOut and Console.SetError to that writer so that console output and error write to the native console. If creating the stream fails, no redirection is performed. -
private static void InitializeInStream()
Creates a FileStream for "CONIN$" and wraps it in a StreamReader, then sets Console.SetIn to that reader so that Console.Read* APIs read from the native console. Note: this method is private and is not called by Initialize() in the current implementation; it can be enabled if input is required. -
private static FileStream CreateFileStream(string name, uint win32DesiredAccess, uint win32ShareMode, FileAccess dotNetFileAccess)
Opens a native file handle to the given console special filename (e.g., "CONOUT$", "CONIN$") by calling CreateFileW. The raw handle is wrapped in a SafeFileHandle (ownsHandle: true). If the handle is valid, it returns a FileStream constructed from that SafeFileHandle using the provided FileAccess; otherwise returns null. This encapsulates P/Invoke handle creation and maps it into a managed stream. -
private static extern int AllocConsole()
(P/Invoke)
Calls kernel32 AllocConsole to allocate a new console for the calling process. -
private static extern uint AttachConsole(uint dwProcessId)
(P/Invoke)
Calls kernel32 AttachConsole to attach the calling process to the console of another process (or the parent when dwProcessId == ATTACH_PARRENT). -
private static extern IntPtr CreateFileW(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile)
(P/Invoke)
Win32 CreateFileW used to open the special console files CONIN$ and CONOUT$.
Notes and caveats: - Windows-only: the class uses kernel32 P/Invoke and will not work on non-Windows platforms. - Permission/hosting environment: calling these APIs may fail under restricted environments (e.g., sandboxes, certain service contexts or when running as a Steam background process). AttachConsole can fail with ERROR_ACCESS_DENIED if the parent process is not attachable. - Stream creation returns null on failure; callers should handle absence of console redirection gracefully. - Initialize() currently only calls InitializeOutStream() when console is successfully allocated/attached; InitializeInStream() is available but not invoked automatically.
Usage Example
// Typical usage from mod startup or game initialization code:
public override void OnCreated() // or similar initialization hook
{
// Try to attach to parent console; if not available, create a new one.
WinConsole.Initialize(alwaysCreateNewConsole: true);
// After Initialize, Console.WriteLine / Console.Error will print to the Windows console.
Console.WriteLine("Console initialized for debugging output.");
}