Console Window
Provides methods to attach, detach, show, and hide a console window in Windows applications that do not normally have a console.
- Allows attaching a console window to a WinForms/WPF application for logging/debugging.
- Automatically restores standard input/output/error streams when attaching.
- Supports hiding or showing the console without detaching it.
- Releasing the console resets the Console streams to null or empty readers/writers.
- Can detect whether a console is already attached.
This class uses kernel32.dll and user32.dll interop to manage the native console window.
VB
Option Strict On
Option Explicit On
Option Infer On
Imports System.IO
Imports System.Runtime.InteropServices
Public NotInheritable Class ConsoleWindow
Private Sub New()
End Sub
<DllImport("kernel32.dll", SetLastError:=True)>
Private Shared Function AllocConsole() As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)>
Private Shared Function FreeConsole() As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)>
Private Shared Function GetConsoleWindow() As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)>
Private Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Boolean
End Function
Private Const SW_HIDE As Integer = 0
Private Const SW_SHOW As Integer = 5
''' <summary>
''' Checks if a console window is currently attached to the process.
''' </summary>
''' <category>Methods</category>
''' <returns><c>True</c> if a console is attached; otherwise, <c>False</c>.</returns>
''' <remarks>
''' This method calls <c>GetConsoleWindow()</c> to determine if a console is active.
''' </remarks>
Public Shared Function IsConsoleAttached() As Boolean
Return GetConsoleWindow() <> IntPtr.Zero
End Function
''' <summary>
''' Ensures that a console window is attached to the current process.
''' </summary>
''' <category>Methods</category>
''' <remarks>
''' <list type="bullet">
''' <item><description>If no console is currently attached, this method allocates a new one.</description></item>
''' <item><description>It also redirects the standard input/output/error streams to the new console.</description></item>
''' <item><description>Useful for attaching a console to GUI applications at runtime.</description></item>
''' </list>
''' </remarks>
Public Shared Sub EnsureAttached()
If GetConsoleWindow() = IntPtr.Zero Then
AllocConsole()
ReopenConsoleStreams()
End If
End Sub
''' <summary>
''' Hides the console window, if currently attached.
''' </summary>
''' <category>Methods</category>
''' <remarks>
''' This method does not detach the console, it only hides it from view.
''' </remarks>
Public Shared Sub Hide()
Dim h = GetConsoleWindow()
If h <> IntPtr.Zero Then ShowWindow(h, SW_HIDE)
End Sub
''' <summary>
''' Shows the console window. If no console is attached, it allocates one.
''' </summary>
''' <category>Methods</category>
''' <remarks>
''' <list type="bullet">
''' <item><description>If a console is already attached, it is simply shown using <c>ShowWindow</c>.</description></item>
''' <item><description>If no console is attached, a new one is allocated and I/O streams are initialized.</description></item>
''' </list>
''' </remarks>
Public Shared Sub ShowUp()
Dim h = GetConsoleWindow()
If h = IntPtr.Zero Then
AllocConsole()
ReopenConsoleStreams()
Else
ShowWindow(h, SW_SHOW)
End If
End Sub
''' <summary>
''' Detaches the console from the current process and nullifies standard I/O streams.
''' </summary>
''' <category>Methods</category>
''' <remarks>
''' <list type="bullet">
''' <item><description>This method sets <c>Console.Out</c> and <c>Console.Error</c> to <c>TextWriter.Null</c>.</description></item>
''' <item><description>It also sets <c>Console.In</c> to a dummy <c>StringReader</c>.</description></item>
''' <item><description>Then it calls <c>FreeConsole()</c> to release the native console.</description></item>
''' </list>
''' </remarks>
Public Shared Sub Detach()
Dim h = GetConsoleWindow()
If h <> IntPtr.Zero Then
Console.SetOut(TextWriter.Null)
Console.SetError(TextWriter.Null)
Console.SetIn(New StringReader(String.Empty))
FreeConsole()
End If
End Sub
''' <summary>
''' Rebinds the standard console input/output/error streams to the native console.
''' </summary>
''' <category>Methods</category>
''' <remarks>
''' Called internally after allocating a new console to ensure <c>Console.ReadLine</c>,
''' <c>Console.WriteLine</c>, etc. work correctly.
''' </remarks>
Private Shared Sub ReopenConsoleStreams()
Dim stdOut As Stream = Console.OpenStandardOutput()
Dim wOut As New StreamWriter(stdOut) With {.AutoFlush = True}
Console.SetOut(wOut)
Dim stdErr As Stream = Console.OpenStandardError()
Dim wErr As New StreamWriter(stdErr) With {.AutoFlush = True}
Console.SetError(wErr)
Dim stdIn As Stream = Console.OpenStandardInput()
Dim rIn As New StreamReader(stdIn)
Console.SetIn(rIn)
End Sub
End Class