3

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.

Community
  • 1
  • 1
Anthony Nichols
  • 1,586
  • 2
  • 25
  • 50
  • Why just don't use a child window for that? Anyway, check this topic... https://groups.google.com/group/microsoft.public.dotnet.languages.csharp/tree/browse_frm/thread/c72efe6c358eca9e/588a7bf4cfb4832?pli=1 – tukaef Jan 19 '13 at 17:52
  • 1
    This approach seems wrong from the start: if your application is started from a command prompt, your application doesn't get a new console window, and your code attempts to hide a window that isn't yours to hide. –  Jan 19 '13 at 17:53
  • Thanks -- It looks like I may need to go with an alternate method. It just seemed so simple to use a window that was already there. – Anthony Nichols Jan 19 '13 at 17:58
  • If you use Visual Studio, you can use Debug.Write[Line] instead, which will popup in the Visual Studio Debug window. No console needed – default Jan 19 '13 at 20:02
  • The idea is that is something acts strange, or the end user wants to see what is going on behind the scenes they can unhide the console window and see a log of what has been going on. A pop-up window is intrusive. – Anthony Nichols Jan 19 '13 at 22:10

2 Answers2

5

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.

Anthony Nichols
  • 1,586
  • 2
  • 25
  • 50
0

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.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
  • 1
    I attempted to create a console using AllocConsole as show here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682528(v=vs.85).aspx but the main application still closes when I close the Console Window. – Anthony Nichols Jan 19 '13 at 18:49
  • 1
    If that's the case, there may not be a way to disable this behavior in the first place. You could look into workarounds like having a separate process for the console, or disabling the exit button and instead offering another, controlled way to *hide* the console window. – Theodoros Chatzigiannakis Jan 19 '13 at 19:17