Output Console.WriteLine from WPF Windows Applications to actual console

后端 未结 4 1202
青春惊慌失措
青春惊慌失措 2020-11-29 04:27

Background: I am struggling to add command line and batch processing capabilities to an existing WPF Windows Application. When I detect some options at startup I su

相关标签:
4条回答
  • 2020-11-29 05:03

    A WPF application will not have a console by default, but you can easily create one for it and then write to it just like in a console app. I've used this helper class before:

    public class ConsoleHelper
    {
        /// <summary>
        /// Allocates a new console for current process.
        /// </summary>
        [DllImport("kernel32.dll")]
        public static extern Boolean AllocConsole();
    
        /// <summary>
        /// Frees the console.
        /// </summary>
        [DllImport("kernel32.dll")]
        public static extern Boolean FreeConsole();
    }
    

    To use this in your example, you should be able to do this:

    namespace WpfConsoleTest
    {
        public partial class App : Application
        {
            protected override void OnStartup(StartupEventArgs e)
            {
                ConsoleHelper.AllocConsole(); 
                Console.WriteLine("Start");
                System.Threading.Thread.Sleep(1000);
                Console.WriteLine("Stop");
                ConsoleHelper.FreeConsole();
                Shutdown(0);
            }
        }
    }
    

    And now, if you run it from the command line, you should see "Start" and "Stop" written to the console.

    0 讨论(0)
  • 2020-11-29 05:04

    In the project properties, you can change the project type from a Windows application to a Console application, and AFAIK the only difference is that you get a console to use throughout the application's lifetime. I haven't tried it with WPF though.

    If you want to open and close a console, you should use Alloc/FreeConsole, but it is usually simpler to change the project type.

    0 讨论(0)
  • 2020-11-29 05:17

    After digging up a bit, I found this answer. The code is now:

    namespace WpfConsoleTest
    {
        public partial class App : Application
        {
            [DllImport("Kernel32.dll")]
            public static extern bool AttachConsole(int processId);
    
            protected override void OnStartup(StartupEventArgs e)
            {
                AttachConsole(-1);
                Console.WriteLine("Start");
                System.Threading.Thread.Sleep(1000);
                Console.WriteLine("Stop");
                Shutdown(0);
            }
        }
    }
    

    Calling the exe directly still has a nasty side effect, connected with the call returning immediately:

    C:\test>WpfConsoleTest.exe
    
    C:\test>Start
    Stop
    
    ^^^^
    The cursor will stay here waiting for the user to press enter!
    

    The solution is, once again, to use start:

    C:\test>start /wait WpfConsoleTest.exe
    Start
    Stop
    

    Thanks for input!

    0 讨论(0)
  • 2020-11-29 05:27

    What I've done in the past is to make it a console application and call P/Invoke to hide the app's associated Console window once I've shown my WPF Window:

    //added using statements per comments...
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
        internal sealed class Win32
        {
            [DllImport("user32.dll")]
            static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    
            public static void HideConsoleWindow()
            {
                IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;
    
                if (hWnd != IntPtr.Zero)
                {
                    ShowWindow(hWnd, 0); // 0 = SW_HIDE
                }
            }
        }
    
    0 讨论(0)
提交回复
热议问题