5

I have a small application who should be executed in two modes: non UI or WPF Window. It should depend on command line arguments.

In each mode, I need to show some feedback log:

  1. In WPF Window mode, WPF is going to take care of visualizing logs,
  2. In no UI mode, I need a console to show logs. If my app have been started from a console (mainly cmd.exe), I'd like to use it without opening a new one. If my app have been started outside of a console (double click on explorer, a CreateProcess, ...), I need to create a new console to output my results and wait for a Readkey to close it.

I have found:

And I know I can statically choose between "Windows Application" or "Console Application" in project property.

Choosing "Windows Application", GetConsoleWindow() is always 0 and I don't see how to reuse a previous console.

Choosing "Console Application", I can reuse a previous console but when started from explorer in WPF Window mode, a console is created under my WPF main window.

The question is: how can an application be really dynamic? Either in WPF Window mode, with only a WPF windows (and no console at all) or in non UI, with only one console (starting one or a new created one).

Community
  • 1
  • 1
MuiBienCarlota
  • 2,355
  • 1
  • 28
  • 32

1 Answers1

9

It was a lot easier in Winforms, but its not too hard.

Start off with a WPF Application Project (not a console application project with WPF windows).

Create a new Program.cs class in the root directory, add the following code:

class Program
{
    [DllImport("Kernel32")]
    public static extern void AllocConsole();

    [DllImport("Kernel32")]
    public static extern void FreeConsole();

    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(uint dwProcessId);

    [STAThread]
    public static void Main(string[] args)
    {
        bool madeConsole = false;
        if (args.Length > 0 && args[0] == "console")
        {

            if (!AttachToConsole())
            {
                AllocConsole();
                Console.WriteLine("Had to create a console");
                madeConsole = true;
            }

            Console.WriteLine("Now I'm a console app!");
            Console.WriteLine("Press any key to exit");
            Console.ReadKey(true);

            if (madeConsole)
                FreeConsole();
        }
        else
        {
            WpfApplication1.App.Main();
        }
    }


    public static bool AttachToConsole()
    {
        const uint ParentProcess = 0xFFFFFFFF;
        if (!AttachConsole(ParentProcess))
            return false;

        Console.Clear();
        Console.WriteLine("Attached to console!");
        return true;
    }

}

Now you have a console app or a WPF app. In the Properties, set the start up object as the Program.Main method. In the example above, WpfApplication1.App.Main is the old start up object (defined in the App.xaml.cs file).

Edit this misses one of your requirements about using the existing console and I will edit it as soon as I figure out how to stay in the same console window.

New Edit Now works to use the existing console!

Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
  • I've already experiment this solution. **You are in the case: "Choosing Console Application"**. We can reuse a previous console but when started from explorer, a console is created under WPF main window. – MuiBienCarlota Apr 29 '15 at 15:12
  • @MuiBienCarlota I suggest you try what I did, when starting from windows explorer, you get no console window. I tested many times before posting, no window appears. You may be confused about the project type, this is a WPF Application, not a console application, so don't choose a console application when creating your project. – Ron Beyer Apr 29 '15 at 15:18
  • I did it on your first code and I just give a try to your last code. Starting from a WPF project, added your Program class with new main and changed "Startup object" to your main function and Output type to "Console Application". And I have a console created when my program is started from explorer. – MuiBienCarlota Apr 29 '15 at 15:31
  • I never said change the output type! Leave it as "Windows Application"! – Ron Beyer Apr 29 '15 at 15:32
  • Yes, it works with the the AttachConsole with ATTACH_PARENT_PROCESS. Thanks. – MuiBienCarlota Apr 29 '15 at 15:40
  • I assumed with mistake that a winmain was required with Output type to "Windows Application". – MuiBienCarlota Apr 29 '15 at 15:56