为什么在使用管道从CreateProcess()子进程接收输入之前,我必须多次按ENTER键?

时间:2016-03-13 18:08:22

标签: c++ c windows process

鉴于以下程序,我创建了一个cmd.exe子进程,为什么我在收到命令输出之前按ENTER两次(从标准输出管道读取) ?

我的目标是效仿" true" cmd.exe经验。但是,额外的ENTER点击有点破坏了这种感觉,因为在收到输出之前会有两个提示(来自子进程)。

另外,我想知道,为什么在子进程cmd.exe控制台窗口中没有显示提示?它只是空白,但我看到它仍然接收输入,执行它并发回输出。

很乐意解释这个问题。

...谢谢

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>

#define BUFFSZ 1024

int main(int argc, char* argv[])
{
    char buf[BUFFSZ];

    STARTUPINFO si;
    SECURITY_ATTRIBUTES sa;
    SECURITY_DESCRIPTOR sd;
    PROCESS_INFORMATION pi;

    // Pipe handles
    HANDLE hChildStd_IN_Rd, hChildStd_OUT_Wr, hChildStd_OUT_Rd, hChildStd_IN_Wr;

    printf("Program started...\n");

    ZeroMemory(&sa, sizeof(sa));

    sa.nLength = sizeof(sa);

    // Inheritable handles
    sa.bInheritHandle = true;

    // StdInput pipe
    if (!CreatePipe(&hChildStd_IN_Rd, &hChildStd_IN_Wr, &sa, 0))
    {
        printf("CreatePipe() failed\n");
        return -1;
    }

    // StdOutput pipe
    if (!CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &sa, 0))
    {
        printf("CreatePipe() failed\n");
        return -1;
    }

    GetStartupInfo(&si);

    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_SHOW;
    si.hStdOutput = hChildStd_OUT_Wr;
    si.hStdError = hChildStd_OUT_Wr;
    si.hStdInput = hChildStd_IN_Rd;

    ZeroMemory(&pi, sizeof(pi));

    // Create child process
    if (!CreateProcess(TEXT("C:\\Windows\\System32\\cmd.exe"), NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
        NULL, NULL, &si, &pi))
    {
        printf("CreateProcess() failed\n");
        return -1;
    }

    unsigned long exit; // Exit code
    unsigned long bread; // Bytes read
    unsigned long avail; // Bytes available

    ZeroMemory(buf, sizeof(buf));

    for (;;)
    {
        // Get termination status of child process
        if (!GetExitCodeProcess(pi.hProcess, &exit)) {
            printf("GetExitCodeProcess() failed\n");
            return -1;
        }

        if (exit != STILL_ACTIVE) {
            break;
        }

        // Check to see if data available in pipe
        PeekNamedPipe(hChildStd_OUT_Rd, buf, BUFFSZ, &bread, &avail, NULL);

        if (bread != 0)
        {
            ZeroMemory(buf, sizeof(buf));


            if (avail > BUFFSZ)
            {
                while (bread >= BUFFSZ)
                {
                    ReadFile(hChildStd_OUT_Rd, buf, BUFFSZ, &bread, NULL); 
                    printf("%s", buf);
                    ZeroMemory(buf, sizeof(buf));
                }
            }
            else {
                // Read all data from StdOut pipe in one chunk
                ReadFile(hChildStd_OUT_Rd, buf, BUFFSZ, &bread, NULL);
                printf("%s", buf);
            }
        }
        if (_kbhit())      //check for user input.
        {
            ZeroMemory(buf, sizeof(buf));
            *buf = (char)getchar();
            WriteFile(hChildStd_IN_Wr, buf, 1, &bread, NULL); 

            if (*buf == '\r') {
                *buf = '\n';
                WriteFile(hChildStd_IN_Wr, buf, 1, &bread, NULL);                                               
            }
        }
    }

    // Clean up
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    CloseHandle(hChildStd_IN_Rd);
    CloseHandle(hChildStd_OUT_Wr);
    CloseHandle(hChildStd_OUT_Rd);
    CloseHandle(hChildStd_IN_Wr);

    return 0;
}

0 个答案:

没有答案