Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to be dynamically either console application or Windows Application

Tags:

c#

.net

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:

  • how I can create a new console: How to open/close console window dynamically from a wpf application?,
  • how to get current console windows handle to show/hide it: Show/Hide the console window of a C# console application

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).

like image 932
MuiBienCarlota Avatar asked Apr 29 '15 14:04

MuiBienCarlota


1 Answers

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!

like image 78
Ron Beyer Avatar answered Oct 26 '22 08:10

Ron Beyer