If I have set my program to be a Windows Application
, and used the AttachConsole(-1)
API, how do I get Console.WriteLine
to write to the console I launched the application from? It isn't working for me.
In case it is relevant, I'm using Windows 7 x64, and I have UAC enabled. Elevating doesn't seem to solve the problem though, nor does using start /wait
.
Update
Some additional background that might help:
I've just discovered that if I go to the command prompt and type cmd /c MyProgram.exe
, Then console output works. The same is true if I launch a command prompt, open a cmd.exe
sub-process, and run the program from that sub-shell.
I've also tried logging out and back in, running from a cmd.exe launched from the start menu (as opposed to right-click -> command prompt), and running from a console2 instance. None of those work.
Background
I've read on other sites and in several SO answers that I can call the win32 API AttachConsole
to bind my Windows Application to the console that ran my program, so I can have something that is "both a console application, and a Windows application".
For example, this question: Is it possible to log message to cmd.exe in C#/.Net?.
I've written a bunch of logic to make this work (using several other APIs), and I have gotten every other scenario to work (including redirection, which others have claimed won't work). The only scenario left is to get Console.WriteLine
to write to the console I launched my program with. From everything I've read this is supposed to work if I use AttachConsole
.
Repro
Here's a minimal sample - Note that the project is set to be a Windows Application
:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
class Program
{
[STAThread]
static void Main(string[] args)
{
if (!AttachConsole(-1))
{
MessageBox.Show(
new Win32Exception(Marshal.GetLastWin32Error())
.ToString()
);
}
Console.WriteLine("Test");
}
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool AttachConsole(int processId);
}
AllocConsole
in my real app).If I call Marshal.GetLastWin32Error
after the call to Console.WriteLine
, I get the error "System.ComponentModel.Win32Exception (0x80004005): The handle is invalid". I suspect that attaching to the console is causing Console.Out
to get messed up, but I'm not sure how to fix it.
This is how I do it in Winforms. Using WPF would be similar.
static class SybilProgram
{
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0)
{
// Command line given, display console
if ( !AttachConsole(-1) ) // Attach to a parent process console
AllocConsole(); // Alloc a new console if none available
ConsoleMain(args);
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); // instantiate the Form
}
}
private static void ConsoleMain(string[] args)
{
Console.WriteLine("Command line = {0}", Environment.CommandLine);
for (int ix = 0; ix < args.Length; ++ix)
Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
Console.ReadLine();
}
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);
}