Introduction
In C#, you can show or hide the console window at runtime using the Windows API functions ShowWindow and GetConsoleWindow via P/Invoke. This is useful for background services, system tray applications, or programs that should run without a visible console. You can also set the project output type to "Windows Application" to hide the console by default at startup, then show it programmatically when needed.
Using P/Invoke to Show/Hide
1using System;
2using System.Runtime.InteropServices;
3
4class Program
5{
6 [DllImport("kernel32.dll")]
7 static extern IntPtr GetConsoleWindow();
8
9 [DllImport("user32.dll")]
10 static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
11
12 const int SW_HIDE = 0;
13 const int SW_SHOW = 5;
14 const int SW_MINIMIZE = 6;
15 const int SW_RESTORE = 9;
16
17 static void Main()
18 {
19 var handle = GetConsoleWindow();
20
21 // Hide the console window
22 ShowWindow(handle, SW_HIDE);
23
24 // Do background work...
25 System.Threading.Thread.Sleep(3000);
26
27 // Show it again
28 ShowWindow(handle, SW_SHOW);
29
30 Console.WriteLine("Console is visible again!");
31 Console.ReadLine();
32 }
33}
GetConsoleWindow() returns the handle to the console window associated with the current process. ShowWindow() changes its visibility state.
Helper Class
Wrap the P/Invoke calls in a reusable class:
1public static class ConsoleWindow
2{
3 [DllImport("kernel32.dll")]
4 private static extern IntPtr GetConsoleWindow();
5
6 [DllImport("user32.dll")]
7 private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
8
9 private const int SW_HIDE = 0;
10 private const int SW_SHOW = 5;
11 private const int SW_MINIMIZE = 6;
12
13 private static readonly IntPtr Handle = GetConsoleWindow();
14
15 public static void Hide() => ShowWindow(Handle, SW_HIDE);
16 public static void Show() => ShowWindow(Handle, SW_SHOW);
17 public static void Minimize() => ShowWindow(Handle, SW_MINIMIZE);
18
19 public static bool IsVisible
20 {
21 get
22 {
23 // IsWindowVisible returns true if the window is visible
24 return IsWindowVisible(Handle);
25 }
26 }
27
28 [DllImport("user32.dll")]
29 private static extern bool IsWindowVisible(IntPtr hWnd);
30}
31
32// Usage
33ConsoleWindow.Hide();
34// ... background work ...
35ConsoleWindow.Show();
Hide Console at Startup (Project Setting)
Change the project output type to suppress the console window from the start:
1<!-- In your .csproj file -->
2<PropertyGroup>
3 <OutputType>WinExe</OutputType> <!-- Instead of 'Exe' -->
4</PropertyGroup>
Or in Visual Studio: Project Properties > Application > Output Type > Windows Application.
With WinExe, no console window appears at startup. You can still use Console.WriteLine() — the output goes nowhere unless you allocate a console:
1[DllImport("kernel32.dll")]
2static extern bool AllocConsole();
3
4[DllImport("kernel32.dll")]
5static extern bool FreeConsole();
6
7static void Main()
8{
9 // No console visible (WinExe)
10
11 // Allocate a console when needed
12 AllocConsole();
13 Console.WriteLine("Now I have a console!");
14 Console.ReadLine();
15 FreeConsole();
16}
System Tray Application with Hidden Console
A common pattern is to hide the console and show a system tray icon:
1using System;
2using System.Drawing;
3using System.Windows.Forms;
4using System.Runtime.InteropServices;
5
6class TrayApp
7{
8 [DllImport("kernel32.dll")]
9 static extern IntPtr GetConsoleWindow();
10
11 [DllImport("user32.dll")]
12 static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
13
14 static NotifyIcon trayIcon;
15
16 static void Main()
17 {
18 // Hide console
19 ShowWindow(GetConsoleWindow(), 0);
20
21 // Create tray icon
22 trayIcon = new NotifyIcon
23 {
24 Icon = SystemIcons.Application,
25 Text = "My Background App",
26 Visible = true,
27 ContextMenuStrip = new ContextMenuStrip()
28 };
29
30 trayIcon.ContextMenuStrip.Items.Add("Show Console", null, (s, e) =>
31 ShowWindow(GetConsoleWindow(), 5));
32 trayIcon.ContextMenuStrip.Items.Add("Exit", null, (s, e) =>
33 Application.Exit());
34
35 Application.Run();
36 }
37}
Redirecting Console Output
When the console is hidden, you may want to redirect output to a file:
1using System.IO;
2
3// Redirect Console.WriteLine to a log file
4var writer = new StreamWriter("app.log", append: true) { AutoFlush = true };
5Console.SetOut(writer);
6Console.SetError(writer);
7
8Console.WriteLine("This goes to app.log, not the hidden console");
.NET Generic Host (Modern Approach)
For background services in .NET 6+, use the Generic Host instead of hiding a console:
1using Microsoft.Extensions.Hosting;
2
3var builder = Host.CreateApplicationBuilder(args);
4builder.Services.AddHostedService<MyBackgroundService>();
5var host = builder.Build();
6host.Run();
7
8class MyBackgroundService : BackgroundService
9{
10 protected override async Task ExecuteAsync(CancellationToken ct)
11 {
12 while (!ct.IsCancellationRequested)
13 {
14 // Do work
15 await Task.Delay(1000, ct);
16 }
17 }
18}
This runs as a proper service without any console window and can be deployed as a Windows Service with UseWindowsService().
Common Pitfalls
Windows-only APIs: GetConsoleWindow, ShowWindow, AllocConsole, and FreeConsole are Windows-specific. They do not work on Linux or macOS. For cross-platform apps, use .NET Generic Host for background services instead.
GetConsoleWindow returning IntPtr.Zero: If the process has no console (e.g., started as a Windows Service or with WinExe output type), GetConsoleWindow() returns IntPtr.Zero. Check for this before calling ShowWindow().
Console.ReadLine blocking after hide: If the console is hidden while Console.ReadLine() is waiting, the application hangs because the user cannot type. Cancel or skip input reads before hiding.
Multiple calls to AllocConsole: AllocConsole() fails if a console is already attached. Call FreeConsole() first if you need to reallocate, or check the return value of GetConsoleWindow().
Flash of console window at startup: With OutputType=Exe, the console briefly appears before ShowWindow(handle, SW_HIDE) runs. Use OutputType=WinExe and AllocConsole() only when needed to avoid the flash.
Summary
Use GetConsoleWindow() and ShowWindow() via P/Invoke to show/hide the console at runtime
Set OutputType to WinExe in the .csproj to prevent the console from appearing at startup
Use AllocConsole() to create a console window on demand for WinExe applications
Redirect Console.SetOut() to a file when the console is hidden to preserve log output
For modern .NET background services, use Host.CreateApplicationBuilder with BackgroundService instead of hiding a console window
These APIs are Windows-only — use cross-platform alternatives for Linux/macOS deployment