Output Console.Writeline from Wpf Windows Applications to Actual Console

Output Console.WriteLine from WPF Windows Applications to actual console

After digging up a bit, I found this answer. The code is now:

namespace WpfConsoleTest
{
public partial class App : Application
{
[DllImport("Kernel32.dll")]
public static extern bool AttachConsole(int processId);

protected override void OnStartup(StartupEventArgs e)
{
AttachConsole(-1);
Console.WriteLine("Start");
System.Threading.Thread.Sleep(1000);
Console.WriteLine("Stop");
Shutdown(0);
}
}
}

Calling the exe directly still has a nasty side effect, connected with the call returning immediately:

C:\test>WpfConsoleTest.exe

C:\test>Start
Stop

^^^^
The cursor will stay here waiting for the user to press enter!

The solution is, once again, to use start:

C:\test>start /wait WpfConsoleTest.exe
Start
Stop

Thanks for input!

No output to console from a WPF application?

You'll have to create a Console window manually before you actually call any Console.Write methods. That will init the Console to work properly without changing the project type (which for WPF application won't work).

Here's a complete source code example, of how a ConsoleManager class might look like, and how it can be used to enable/disable the Console, independently of the project type.

With the following class, you just need to write ConsoleManager.Show() somewhere before any call to Console.Write...

[SuppressUnmanagedCodeSecurity]
public static class ConsoleManager
{
private const string Kernel32_DllName = "kernel32.dll";

[DllImport(Kernel32_DllName)]
private static extern bool AllocConsole();

[DllImport(Kernel32_DllName)]
private static extern bool FreeConsole();

[DllImport(Kernel32_DllName)]
private static extern IntPtr GetConsoleWindow();

[DllImport(Kernel32_DllName)]
private static extern int GetConsoleOutputCP();

public static bool HasConsole
{
get { return GetConsoleWindow() != IntPtr.Zero; }
}

/// <summary>
/// Creates a new console instance if the process is not attached to a console already.
/// </summary>
public static void Show()
{
//#if DEBUG
if (!HasConsole)
{
AllocConsole();
InvalidateOutAndError();
}
//#endif
}

/// <summary>
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
/// </summary>
public static void Hide()
{
//#if DEBUG
if (HasConsole)
{
SetOutAndErrorNull();
FreeConsole();
}
//#endif
}

public static void Toggle()
{
if (HasConsole)
{
Hide();
}
else
{
Show();
}
}

static void InvalidateOutAndError()
{
Type type = typeof(System.Console);

System.Reflection.FieldInfo _out = type.GetField("_out",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);

System.Reflection.FieldInfo _error = type.GetField("_error",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);

System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);

Debug.Assert(_out != null);
Debug.Assert(_error != null);

Debug.Assert(_InitializeStdOutError != null);

_out.SetValue(null, null);
_error.SetValue(null, null);

_InitializeStdOutError.Invoke(null, new object[] { true });
}

static void SetOutAndErrorNull()
{
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
}
}

Is it possible to have a WPF application print console output?

We have special class for this purpose:

internal static class ConsoleAllocator
{
[DllImport(@"kernel32.dll", SetLastError = true)]
static extern bool AllocConsole();

[DllImport(@"kernel32.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport(@"user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

const int SwHide = 0;
const int SwShow = 5;

public static void ShowConsoleWindow()
{
var handle = GetConsoleWindow();

if (handle == IntPtr.Zero)
{
AllocConsole();
}
else
{
ShowWindow(handle, SwShow);
}
}

public static void HideConsoleWindow()
{
var handle = GetConsoleWindow();

ShowWindow(handle, SwHide);
}
}

Just call ConsoleAllocator.ShowConsoleWindow() and then write to Console

WPF / Console Hybrid Application

Your best bet would be to abstract out the code that actually does the work to a separate class library that has no UI and then create two applications one Console, the other WPF that call this.

A console application and an WPF application have entirely different application models so you can't reuse the same code in both applications.

Having a separate class library allows you do other things like use it in other applications such as a web site or client/server architecture.



Related Topics



Leave a reply



Submit