I do this in my C# window programs (WInforms or WPF) using a Win32 console window. I have a small class that wraps some basic Win32 APIs, thin I create a console when the program begins. This is just an example: in 'real life' you'd use a setting or some other thing to only enable the console when you needed it.
using System;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using MWin32Api;
namespace WFConsole
{
static class Program
{
static private SafeFileHandle ConsoleHandle;
/// <summary>
/// Initialize the Win32 console for this process.
/// </summary>
static private void InitWin32Console()
{
if ( !K32.AllocConsole() ) {
MessageBox.Show( "Cannot allocate console",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
return;
}
IntPtr handle = K32.CreateFile(
"CONOUT$", // name
K32.GENERIC_WRITE | K32.GENERIC_READ, // desired access
K32.FILE_SHARE_WRITE | K32.FILE_SHARE_READ, // share access
null, // no security attributes
K32.OPEN_EXISTING, // device already exists
0, // no flags or attributes
IntPtr.Zero ); // no template file.
ConsoleHandle = new SafeFileHandle( handle, true );
if ( ConsoleHandle.IsInvalid ) {
MessageBox.Show( "Cannot create diagnostic console",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
return;
}
//
// Set the console screen buffer and window to a reasonable size
// 1) set the screen buffer sizse
// 2) Get the maximum window size (in terms of characters)
// 3) set the window to be this size
//
const UInt16 conWidth = 256;
const UInt16 conHeight = 5000;
K32.Coord dwSize = new K32.Coord( conWidth, conHeight );
if ( !K32.SetConsoleScreenBufferSize( ConsoleHandle.DangerousGetHandle(), dwSize ) ) {
MessageBox.Show( "Can't get console screen buffer information.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
return;
}
K32.Console_Screen_Buffer_Info SBInfo = new K32.Console_Screen_Buffer_Info();
if ( !K32.GetConsoleScreenBufferInfo( ConsoleHandle.DangerousGetHandle(), out SBInfo ) ) {
MessageBox.Show( "Can't get console screen buffer information.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
K32.Small_Rect sr; ;
sr.Left = 0;
sr.Top = 0;
sr.Right = 132 - 1;
sr.Bottom = 51 - 1;
if ( !K32.SetConsoleWindowInfo( ConsoleHandle.DangerousGetHandle(), true, ref sr ) ) {
MessageBox.Show( "Can't set console screen buffer information.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
return;
}
IntPtr conHWND = K32.GetConsoleWindow();
if ( conHWND == IntPtr.Zero ) {
MessageBox.Show( "Can't get console window handle.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
return;
}
if ( !U32.SetForegroundWindow( conHWND ) ) {
MessageBox.Show( "Can't set console window as foreground.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
return;
}
K32.SetConsoleTitle( "Test - Console" );
Trace.Listeners.Add( new ConsoleTraceListener() );
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
InitWin32Console();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
Application.Run( new Main() );
}
}
}
using System;
using System.Runtime.InteropServices;
namespace MWin32Api
{
#region Kernel32 Functions
//--------------------------------------------------------------------------
/// <summary>
/// Functions in Kernel32.dll
/// </summary>
public sealed class K32
{
#region Data Structures, Types and Constants
//----------------------------------------------------------------------
// Data Structures, Types and Constants
//
[StructLayout( LayoutKind.Sequential )]
public class SecurityAttributes
{
public UInt32 nLength;
public UIntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout( LayoutKind.Sequential, Pack = 1, Size = 4 )]
public struct Coord
{
public Coord( UInt16 tx, UInt16 ty )
{
x = tx;
y = ty;
}
public UInt16 x;
public UInt16 y;
}
[StructLayout( LayoutKind.Sequential, Pack = 1, Size = 8 )]
public struct Small_Rect
{
public Int16 Left;
public Int16 Top;
public Int16 Right;
public Int16 Bottom;
public Small_Rect( short tLeft, short tTop, short tRight, short tBottom )
{
Left = tLeft;
Top = tTop;
Right = tRight;
Bottom = tBottom;
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1, Size = 24 )]
public struct Console_Screen_Buffer_Info
{
public Coord dwSize;
public Coord dwCursorPosition;
public UInt32 wAttributes;
public Small_Rect srWindow;
public Coord dwMaximumWindowSize;
}
public const int ZERO_HANDLE_VALUE = 0;
public const int INVALID_HANDLE_VALUE = -1;
#endregion
#region Console Functions
//----------------------------------------------------------------------
// Console Functions
//
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool AllocConsole();
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool SetConsoleScreenBufferSize(
IntPtr hConsoleOutput,
Coord dwSize );
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool GetConsoleScreenBufferInfo(
IntPtr hConsoleOutput,
out Console_Screen_Buffer_Info lpConsoleScreenBufferInfo );
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool SetConsoleWindowInfo(
IntPtr hConsoleOutput,
bool bAbsolute,
ref Small_Rect lpConsoleWindow );
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern IntPtr GetConsoleWindow();
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool SetConsoleTitle(
string Filename );
#endregion
#region Create File
//----------------------------------------------------------------------
// Create File
//
public const UInt32 CREATE_NEW = 1;
public const UInt32 CREATE_ALWAYS = 2;
public const UInt32 OPEN_EXISTING = 3;
public const UInt32 OPEN_ALWAYS = 4;
public const UInt32 TRUNCATE_EXISTING = 5;
public const UInt32 FILE_SHARE_READ = 1;
public const UInt32 FILE_SHARE_WRITE = 2;
public const UInt32 GENERIC_WRITE = 0x40000000;
public const UInt32 GENERIC_READ = 0x80000000;
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern IntPtr CreateFile(
string Filename,
UInt32 DesiredAccess,
UInt32 ShareMode,
SecurityAttributes SecAttr,
UInt32 CreationDisposition,
UInt32 FlagsAndAttributes,
IntPtr TemplateFile );
#endregion
#region Win32 Miscelaneous
//----------------------------------------------------------------------
// Miscelaneous
//
[DllImport( "kernel32.dll" )]
public static extern bool CloseHandle( UIntPtr handle );
#endregion
//----------------------------------------------------------------------
private K32()
{
}
}
#endregion
//--------------------------------------------------------------------------
/// <summary>
/// Functions in User32.dll
/// </summary>
#region User32 Functions
public sealed class U32
{
[StructLayout( LayoutKind.Sequential )]
public struct Rect
{
public Int32 Left;
public Int32 Top;
public Int32 Right;
public Int32 Bottom;
public Rect( short tLeft, short tTop, short tRight, short tBottom )
{
Left = tLeft;
Top = tTop;
Right = tRight;
Bottom = tBottom;
}
}
[DllImport( "user32.dll" )]
public static extern bool GetWindowRect(
IntPtr hWnd,
[In][MarshalAs( UnmanagedType.LPStruct )]Rect lpRect );
[DllImport( "user32.dll", SetLastError = true )]
public static extern bool SetForegroundWindow(
IntPtr hWnd );
//----------------------------------------------------------------------
private U32()
{
}
} // U32 class
#endregion
} // MWin32Api namespace