c++ - 通过将标准输入/输出重定向到管道来制作子进程

标签 c++ winapi pipe stdio

我正在尝试使用重定向的stdin / stdout创建一个子进程。
我正在创建一个管道来重定向标准输入并将标准输出写入文件。

这是我尝试过的

#include <Windows.h>
#include <iostream>

int main()
{
    STARTUPINFOA sInfo;
    PROCESS_INFORMATION pInfo;
    SECURITY_ATTRIBUTES sAttr;
    ZeroMemory(&sInfo, sizeof(sInfo));
    ZeroMemory(&pInfo, sizeof(pInfo));
    ZeroMemory(&sAttr, sizeof(sAttr));
    sInfo.cb = sizeof(sInfo);
    sAttr.bInheritHandle = true;
    HANDLE fileTest = CreateFileA("hello.txt", GENERIC_READ | GENERIC_WRITE, 0, &sAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE stdinPipe = CreateNamedPipeA("\\\\.\\pipe\\DokiDokiIn", PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, &sAttr);
    sInfo.hStdInput = stdinPipe;
    sInfo.hStdOutput = fileTest;
    sInfo.hStdError = fileTest;
    sInfo.dwFlags |= STARTF_USESTDHANDLES;
    char cmdLine[] = "cmd.exe";
    bool success = CreateProcessA("C:\\WINDOWS\\system32\\cmd.exe", NULL, &sAttr, NULL, NULL, NULL, NULL, NULL, &sInfo, &pInfo);
    if (!success) {
        std::cout << "CreateProcessA() failed with error " << GetLastError() << "\n";
    }
    std::cout << GetLastError() << "\n";
    return 0;
}

每当我将STARTF_USESTDHANDLES指定为dwFlags时,这似乎都不起作用,打开的进程会立即关闭(或不确定,根本无法打开)。当我不指定标志但未重定向I / O时,它可以工作。
另外,正如预期的那样,使用我的管道客户端对其进行写入无法正常工作,因此无法获取该管道的句柄。
CreateFile始终为true,并且句柄值似乎有效,GetLastError()返回0,但程序仅退出且子进程没有弹出窗口,即使它在后台运行也无法写入。

最佳答案

根据您表示的代码,发现两个问题:

  • bInheritHandlesCreateProcessA参数设置为TRUE而不是NULL,以使调用进程中的每个可继承句柄都被新进程继承(这里是cmd.exe)。
  • cmd.exe在启动和退出后显示版本信息。如果要阻止它退出,可以为cmd.exe设置命令行以使其连续运行。

  • 小费:

    函数失败后立即调用 GetLastError() ,否则其他函数可能会将错误代码设置为zero

    以下是我的示例工作。你可以试试看。
    int main()
    {
        STARTUPINFOA sInfo;
        PROCESS_INFORMATION pInfo;
        SECURITY_ATTRIBUTES sAttr;
        ZeroMemory(&sInfo, sizeof(sInfo));
        ZeroMemory(&pInfo, sizeof(pInfo));
        ZeroMemory(&sAttr, sizeof(sAttr));
        sInfo.cb = sizeof(sInfo);
        sAttr.bInheritHandle = true;
        HANDLE fileTest = CreateFileA("hello.txt", GENERIC_READ | GENERIC_WRITE, 0, &sAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        HANDLE stdinPipe = CreateNamedPipeA("\\\\.\\pipe\\DokiDokiIn", PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, &sAttr);
        sInfo.hStdInput = stdinPipe;
        sInfo.hStdOutput = fileTest;
        sInfo.hStdError = fileTest;
        sInfo.dwFlags |= STARTF_USESTDHANDLES;
    
        char input[] = "ping www.google.com -t";
        char cmd[] = "cmd.exe";
        // initialize cmd
        char cmdline[MAX_PATH];
        sprintf_s(cmdline, sizeof(cmdline), "%s /c %s", cmd, input);
        bool success = CreateProcessA("C:\\WINDOWS\\system32\\cmd.exe", cmdline, &sAttr, NULL, TRUE, NULL, NULL, NULL, &sInfo, &pInfo);
        if (!success) {
            DWORD errCode = GetLastError();
            std::cout << "CreateProcessA() failed with error " << errCode << "\n";
        }
    
        return 0;
    }
    

    关于c++ - 通过将标准输入/输出重定向到管道来制作子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62095603/

    相关文章:

    c++ - OMNeT++:对 `typeinfo for inet::IMobility' 的 undefined reference

    c++ - 插入到链表末尾

    c++ - 将大小为 4 字节的管道读入 4 字节 int 如何返回更多数据?

    terminal - pty 和管道之间的区别

    c++ - 为什么 LD_PRELOAD 不适用于加载的共享库之一?

    c++ - 使用 sin() 生成的声音中的金属声音

    c++ - Win32 : Test if mouse has hovered for a second

    无法在新文本框中显示文本输入

    java - 有没有办法有时需要来自 stdin 的数据,有时不需要 Java 中的数据?

    c - 2 个子进程之间的管道 UNIX C