简体   繁体   中英

How to be dynamically either console application or Windows Application

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

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM