Anthony Nichols
Anthony Nichols

Reputation: 1668

In a WPF app how do you override the Console Close command?

In my WPF application I use the Console Window as a debug/message window - I have options setup to show and hide the window as the user desires and all that works great. The only issue is that when the user closes the Console window it exits the entire program. How can I override this so that when the user click on the X it just hides the Console instead of exiting the application?

this is what I have so far:

const int SW_HIDE = 0;
const int SW_SHOW = 5;
public static bool ConsoleVisible { get; private set; }

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);


public static void HideConsole()
{
    var handle = GetConsoleWindow();
    ShowWindow(handle, SW_HIDE);
    ConsoleVisible = false;

}
public static void ShowConsole()
{
    var handle = GetConsoleWindow();
    ShowWindow(handle, SW_SHOW);
    ConsoleVisible = true;
}

** For people wanting to utilize this you need: using System.Runtime.InteropServices;

This code was derived from this answer: https://stackoverflow.com/a/3571628/649382

** Edit **

Looking around a bit more it seems like this is not possible. I saw an answer here: https://stackoverflow.com/a/12015131/649382 that talks about removing the exit button which would also be acceptable, except it looks like the code is in C++ and I can't figure out it's C# alternative.

** Edit 2 **

I was able to figure out the conversion to C# and have written it as the answer below.

Upvotes: 3

Views: 1645

Answers (2)

Anthony Nichols
Anthony Nichols

Reputation: 1668

So as has been discussed there is no way to prevent the Console Window from closing the WPF/Application Window. Prior to Windows Vista there were some workarounds, but since then they have been removed (probably for security reasons). The work around I was able to come up with was to disable the Exit button on the Console Window and place show/hide options into my application. The application start class looks like this:

using System;
using System.Windows;
using System.Runtime.InteropServices;

namespace MyApp
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            ConsoleVisible = true;
            DisableConsoleExit();
        }

        #region Console Window Commands

        // Show/Hide
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();
        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

        const uint SW_HIDE = 0;
        const uint SW_SHOWNORMAL = 1;
        const uint SW_SHOWNOACTIVATE = 4; // Show without activating
        public static bool ConsoleVisible { get; private set; }

        public static void HideConsole()
        {
            IntPtr handle = GetConsoleWindow();
            ShowWindow(handle, SW_HIDE);
            ConsoleVisible = false;

        }
        public static void ShowConsole(bool active = true)
        {
            IntPtr handle = GetConsoleWindow();
            if (active) { ShowWindow(handle, SW_SHOWNORMAL); }
            else { ShowWindow(handle, SW_SHOWNOACTIVATE); }
            ConsoleVisible = true;
        }

        // Disable Console Exit Button
        [DllImport("user32.dll")]
        static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
        [DllImport("user32.dll")]
        static extern IntPtr DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);

        const uint SC_CLOSE = 0xF060;
        const uint MF_BYCOMMAND = (uint)0x00000000L;

        public static void DisableConsoleExit()
        {
            IntPtr handle = GetConsoleWindow();
            IntPtr exitButton = GetSystemMenu(handle, false);
            if (exitButton != null) DeleteMenu(exitButton, SC_CLOSE, MF_BYCOMMAND);
        }

        #endregion
    }
}

Hope this helps everyone out who may have a similar issue.

Upvotes: 5

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

Reputation: 29223

I think you should look into creating the console using AllocConsole and releasing it using FreeConsole. That way you may be able to give the user the ability to close the console window while keeping your WPF application running.

Upvotes: 0

Related Questions