5

I have a WPF app that, when command line arguments are passed, runs as a command line app. To show / acquire the command line window I use the following code.

When I run the app everything works as expected. If I write anything out to the console during the app then the app doesnt auto exit from the console, I have to press "enter" or basically invoke some kind of ReadLine - Note I am not using ReadLine in my app at all. In fact I can make this behaviour happen only using this simple code. How can I prevent the requirement to "press enter" once the app has run?

public static void Main(string[] args)
{
    if (args.Length == 0)
    {
        App app = new App();
        app.Run(new MainWindow());
    }
    else
    {
        // attach to an parent process console
        if (!NativeMethods.AttachConsole(-1))
        {
            // allocate a new console
            NativeMethods.AllocConsole();
        }

        Console.WriteLine("hey");

        NativeMethods.FreeConsole();
    }
}

I am using the following methods for Alloc / Attach / Free. Note as per Rohit's suggestion I have tried FreeConsole directly after the WriteLine but it still doesnt help

[DllImport("kernel32.dll")]
private static extern bool AllocConsole();

[DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern int FreeConsole();
Chris
  • 26,744
  • 48
  • 193
  • 345

4 Answers4

1

I run into the same issue and can totally agree on Cris' findings.

Looking more closely to the console, I realized that the prompt was printed in the console immediately after running the app. The output text is printed AFTER the prompt.

So basically hitting enter just prints another empty prompt.

E.g. MyWpfApp with Console.WriteLine("hey");

Would look like this:

C:> MyWpfApp

C:> hey

No new and empty prompt here.

The console actually already showed the prompt but added the complete output after that (even with multiple lines of output, which makes it even harder to realize that the prompt was printed BEFORE them).

So the application execution appears to be unfinished but in fact the process is finished and any further key stroke in the console is directly sent to cmd.

phu
  • 43
  • 4
0

Use FreeConsole() method whenever you are done with writing to Console to release the attached Console to your app.

if (!Startup.AttachConsole(-1))
{ 
    // Attach to an parent process console
    Startup.AllocConsole(); // Alloc a new console
}

Console.WriteLine("hey");
Startup.FreeConsole();
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
0

After your modal main window has completed, cleanup all application resources using code similar to the following:

    [STAThread()]
    internal static void Main()
    {
        // [Your startup code here]

        Application app = new Application();
        app.DispatcherUnhandledException += DispatcherUnhandledException;
        app.MainWindow = new MainWindow();
        app.MainWindow.ShowDialog();

        Console.WriteLine("Terminating...");
        Startup.FreeConsole();

        // http://msdn.microsoft.com/en-us/library/ms597014(v=vs.110).aspx
        app.Shutdown(0);      // <-- or Application.Current.Shutdown(0);

        // http://msdn.microsoft.com/en-us/library/system.environment.exit.aspx
        Environment.Exit(0);  // <-- a bit redundant however
    }
Jeff
  • 2,495
  • 18
  • 38
  • I dont actually create both App and Console, I selectively choose. Ill update the question with more code – Chris Apr 11 '14 at 08:24
  • I see. Nevertheless, Environment.Exit(0) should perform the necessary cleanup for you. – Jeff Apr 11 '14 at 11:36
  • unfortunately it still doesnt work... I am left with the console app not returning to the command prompt unless I press enter afterwards – Chris Apr 11 '14 at 13:19
  • You are not pressing Ctrl-F5 to run this, are you? – Jeff Apr 11 '14 at 14:17
  • I just created a test project and used your code, and I don't get the same result. The console disappears immediately after 'hey' is displayed. – Jeff Apr 11 '14 at 14:42
  • To test this I build then run in command prompt, if I run using debugger it exists instantly – Chris Apr 11 '14 at 14:47
  • I see. In that case, the console was not originally allocated by you, and so other references remain, and it will not disappear. You simply attach onto the current console for standard input / output redirection. – Jeff Apr 11 '14 at 15:15
  • Yup exactly, but shouldn't it drop out into the normal command prompt once my app finishes? It works if I dont write anything out to the console (even with the attach in place etc). – Chris Apr 11 '14 at 15:50
0

The problem seems to be by the lazy initialization of Console.Out, when the handle is acquired by GetStdHandle(STD_OUTPUT_HANDLE) To wait for the prompt to return AND piping the console output successfully to a log the app needs to be started with start /b /wait myGuiApp > mylog.txt

All credit goes to arx: https://stackoverflow.com/a/11526152/1374375

Community
  • 1
  • 1
kkCosmo
  • 387
  • 3
  • 7