防止子进程控制台强制关闭

时间:2018-11-26 14:03:44

标签: c++ winapi

我正在从我的主流程中创建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;
}

1 个答案:

答案 0 :(得分: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循环(在break;之后添加v.erase(it);)。