【问题标题】:Prevent application from closing when closing console关闭控制台时阻止应用程序关闭
【发布时间】:2018-11-24 21:38:19
【问题描述】:

我有一个 WinAPI/Win32 应用程序,它还会在打开主窗口之前打开一个控制台窗口(用于调试目的)。我添加了一个安全检查,当主窗口按下 X 按钮时,它会询问“你确定吗?”事物。但是,如果我在控制台上单击 X,它会立即终止应用程序而不询问任何内容。有什么办法可以防止这种情况发生吗? 这是我的代码的 sn-p:

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int nCmdShow)
{
EnableDebug();
WNDCLASSA MainWindow = { 0 };
MainWindow.hbrBackground = (HBRUSH) COLOR_WINDOW;
MainWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
MainWindow.hInstance = hInst;
MainWindow.lpszClassName = "WindowClass";
MainWindow.lpfnWndProc = WndProc;
ATOM result = RegisterClassA(&MainWindow);
if (!result)
{
    MessageBoxA(NULL, "Failed to register window class", "Error", MB_OK);
    return -1;
}
MSG msg = { 0 };
//here the app goes on


 //here is the start of the debug function
    void EnableDebug(){
    if (AllocConsole() == 0)
    {
        MessageBoxA(NULL, "Unable to create a debug window!", "Error", MB_OK);
        return;
    }
    freopen("CONOUT$", "w", stderr);
    SetConsoleTitleA("Debug Window");
    clog.clear();

【问题讨论】:

  • 首先在后台启动您的程序?
  • 不完整、无用的 sn-p 代码应该提供什么价值?
  • 您要解决什么问题?这个问题只是在问,如何解决您提出的解决方案。
  • 您似乎没有理解这个问题。代码的 sn-p 显示了我如何启动我的应用程序和控制台窗口。我要问的是当我关闭控制台时如何使应用程序不关闭。
  • 如果您仅出于调试目的创建控制台 - 您可以轻松地在进程中创建常用窗口(例如创建单独的线程,WC_EDIT windows)并将其 printf 用于调试

标签: c++ winapi


【解决方案1】:

我相信您需要调用SetConsoleCtrlHandler 来提供处理程序例程来处理关闭事件。像这样的:

BOOL WINAPI MyCtrlHandler (DWORD dwCtrlType)
{
    if (dwCtrlType == CTRL_CLOSE_EVENT)
        ...
}

SetConsoleCtrlHandler (MyCtrlHandler, TRUE);

您可能希望以各种方式处理dwCtrlType 的各种值。详情请咨询documentation

【讨论】:

  • 不幸的是,这是行不通的。如果您在关闭控制台事件时未退出应用程序,则在几秒钟后进程将被强制终止外部
  • csrss.exe 外部调用TerminateProcessSTATUS_CONTROL_C_EXIT - stackoverflow.com/questions/26404907/…
  • 禁用控制台上的 X 按钮也是一种选择,但我认为这是不可能的。
  • @DarkAtom 有可能,看我的回答。
  • 类似这样的东西:BOOL CALLBACK ConProc(DWORD dwCtrlType) { if (dwCtrlType == CTRL_CLOSE_EVENT) { SetConsoleCtrlHandler(ConProc, FALSE); FreeConsole(); return TRUE; } } 似乎不起作用。
【解决方案2】:

您可以在控制台窗口disable the close button 防止意外终止您的应用程序:

if( HWND hwnd = GetConsoleWindow() )
{
    if( HMENU hMenu = GetSystemMenu( hwnd, FALSE ) )
    {
        EnableMenuItem( hMenu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED );
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多