【问题标题】:Prevent console of sub processes from force closing防止子进程控制台强制关闭
【发布时间】:2018-11-26 14:03:44
【问题描述】:

我正在从我的主进程创建 5 个子进程并等待所有子进程完成。每个子进程都创建自己的控制台窗口。我想要做的是禁用子进程创建的控制台窗口的关闭按钮。我找不到任何资源来做到这一点。

  • 如何保持子进程的控制台打开,这样如果用户按下控制台的关闭按钮,它就不会关闭?
  • GetExitCodeProcess(pi.hProcess, &exitCode) 总是返回 false 并且来自 GetLastError() 的最后一个错误代码是 5。但 exitCode 的值显示正确的值。为什么会这样?

这是我的代码:

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;

wstring to_wstring(const string& str)
{
    std::wstring ws;
    ws.assign(str.begin(), str.end());
    return ws;
}

vector<PROCESS_INFORMATION> v;

int main(int argc, TCHAR *argv[])
{
    int noOfProcess = 4;
    for (int i = 1; i <= noOfProcess; i++) {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

        auto ws = to_wstring("D:\\programming\\test.exe");
        TCHAR *cmd;
        cmd = new TCHAR[ws.length() + 10];
        _tcscpy_s(cmd, ws.length() + 1, ws.c_str());

        // Start the child process.
        if (!CreateProcess(NULL,   // No module name (use command line)
            cmd,        // Command line
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            true,          // Set handle inheritance to FALSE
            CREATE_NEW_CONSOLE,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory
            &si,            // Pointer to STARTUPINFO structure
            &pi)           // Pointer to PROCESS_INFORMATION structure
            )
        {
            printf("CreateProcess failed (%d).\n", GetLastError());
            return 0;
        }

        cout << "Started Process " << pi.hProcess << endl;
        v.push_back(pi);
    }
    while (v.size()) {
        for (auto it = v.begin(), next_it = v.begin(); it != v.end(); it = next_it) {
            next_it = it; it++;
            PROCESS_INFORMATION &pi = *it;
            DWORD exitCode = 0;
            if (GetExitCodeProcess(pi.hProcess, &exitCode) == FALSE)
            {
                // Always return error code 5 but exitcode is set to correct value
                cout << GetLastError() << endl;
            }
            if (exitCode == STILL_ACTIVE)
                continue;
            cout << "Finished Process " << pi.hProcess << " With exit code " << exitCode << endl;
            // Close process and thread handles.
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
            v.erase(it);
        }
    }
    return 0;
}

【问题讨论】:

  • 一个明显的解决方案是不为您的子进程创建新的控制台。您首先需要新游戏机是否有特定原因?
  • 是的,我需要在这些控制台中显示 exe 的输出。
  • 我通常的解决方案是将输出从孩子重定向到父控制台,并通过在输出前加上孩子的索引来记录输出,例如:child 001: example of output

标签: c++ winapi


【解决方案1】:
  1. 尝试这种方式来禁用子进程中的关闭按钮(你想要禁用关闭按钮的那一刻)。

    DeleteMenu(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_BYCOMMAND);

  2. 根据 MSDN 文档hereGetExitCodeProcess() 的句柄必须具有 PROCESS_QUERY_INFORMATION 访问权限。使用 PROCESS_QUERY_INFORMATION 打开进程。

    OpenProcess(PROCESS_QUERY_INFORMATION, true, pi.dwProcessId);

  3. 我已经测试了您的代码,其中有一个错误。当v.size() = 1it++ 会走出向量,那么*it 就会抛出异常。 在 v.erase(it) 之后,你最好中断并重新启动 for 循环(在v.erase(it); 之后添加break;)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 2016-01-31
    • 1970-01-01
    • 2010-12-19
    相关资源
    最近更新 更多