c++ - 通过 Windows 管道写入进程 STDIN

标签 c++ windows process pipe

我正在尝试创建一个函数,该函数将生成一个程序实例,然后将一些数据通过管道传输到它的 STDIN,然后使用 C++ 读取进程的输出。我查看了位于 here 的 MSDN 示例这让我很困惑,当我尝试使用这个例子时,我得到了一些讨厌的错误代码并且它不起作用。

    HANDLE hWriteOUT, hReadOUT, hWriteIN, hReadIN;
    SECURITY_ATTRIBUTES saPipe = {0};
    PROCESS_INFORMATION procInfo = {0};
    STARTUPINFO procSi;
    DWORD dwWritten, dwRead;
    char buf[512];

    saPipe.nLength = sizeof(SECURITY_ATTRIBUTES);
    saPipe.bInheritHandle = TRUE;
    saPipe.lpSecurityDescriptor= NULL;
    CreatePipe(&hReadOUT, &hWriteOUT, &saPipe, 0);
    SetHandleInformation(hReadOUT, HANDLE_FLAG_INHERIT, 0);
    CreatePipe(&hReadIN, &hWriteIN, &saPipe, 0);
    SetHandleInformation(hReadIN, HANDLE_FLAG_INHERIT, 0);

    ZeroMemory(&procSi, sizeof(STARTUPINFO));
    procSi.cb = sizeof(STARTUPINFO);
    procSi.hStdError = hWriteOUT;
    procSi.hStdOutput = hWriteOUT;
    procSi.hStdInput = hReadIN;
    procSi.dwFlags |= STARTF_USESTDHANDLES;

    CreateProcess(NULL, "cmd", NULL, NULL, TRUE, 0, NULL, NULL, &procSi, &procInfo);
    //Gives me an error code of 18 but returns a 1 when a 0 indicates failure.

    WriteFile(hWriteIN, "notepad", sizeof("notepad"), &dwWritten, NULL);
    cout << GetLastError();  //This gives me error code 18 (ERROR_NO_MORE_FILES)
    ReadFile(hReadOUT, buf, 512, &dwRead, NULL);
    cout << buf;  //This prints "Microsoft Windows [version 6.1.7601]
    CloseHandle(hWriteIN);

代码无法将字符串“notepad”通过管道传输到 cmd.exe,但成功启动了命令 shell。如果我查看任务管理器,会出现多个命令提示符实例,但没有记事本。此外,ReadFile() 函数似乎是唯一有效的函数,但它甚至不是从管道进程(应该生成的记事本)中读取,而是从 CMD 中读取。更糟糕的是,它会截断除读取的第一行以外的所有内容! (CMD 打印“Microsoft Windows....\n Copyright...\n C:\Users\Foo>...\n”但 `ReadFile() 只抓取第一行)

最佳答案

代码的行为符合预期。您似乎误解了很多事情:

1) 如果您希望 cmd.exe 运行它,您需要在命令末尾发送一个 ENTER ("\n")。通常最好在 CreateProcess 中指定要运行的命令,例如,您可以将“cmd/c notepad”指定为命令行,而不仅仅是“cmd”。

2) 您已将管道附加到 cmd.exe 进程的标准输入和输出,因此您当然会看到该进程的输出。如果您不想看到 cmd.exe 的输出,请不要运行它;直接运行您想要的应用程序,例如,您可以将“记事本”指定为要运行的命令行。

3) 从管道读取时,ReadFile一次只返回一个数据 block ,所以需要循环调用。

4) Notepad 是一个 GUI 进程,所以它不使用 stdin 或 stdout。大概这只是一个选择不当的示例,而您实际上想要运行一个命令行应用程序?

5) 除特别说明外,错误代码(由 GetLastError 返回)仅在函数失败时才有意义。您正在使用的函数都不是这种情况的异常,因此检查错误代码没有意义,除非该函数返回零以表明它已失败。

关于c++ - 通过 Windows 管道写入进程 STDIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10119999/

相关文章:

python - 在单独的进程中运行 python

c++ - 错误 : No operator << matches these operands?

c++ - 任何人都知道有什么计划让 ^ 成为 shared_ptr<T> 的简写吗?

windows - CMake 生成的 MinGW Makefile 有引用错误

windows - 以编程方式终止并重新启动 explorer.exe 的最干净的方法是什么?

android - 带有 setRetainInstance(true) 的 Fragment 是否在进程关闭后继续存在?

c++ - 在 Win32 上通过代码安装根 CA 证书

c++ - 哪些组件对于 C++ 项目必不可少,但在公共(public)库中找不到?

c# - 在 C# 中获取屏幕像素颜色的最快方法

windows - 如何编译要从 DMD 链接的 msvc 静态库?