Win32

时间:2017-10-29 01:43:03

标签: c# c++ .net winapi

这是关于启动子进程和重定向输出。

在.NET中,我们可以使用Process.RedirectStandard ...重定向标准IO,并使用Process.OutputDataReceived接收事件写入输出时的事件。

我想用Win32 API在本机C ++中实现它。

当我查看源代码(12)时,看起来它正在使用Stream.BeginRead方法,但我无法找到如何实现此方法。

我认为它是通过创建一个新线程(或.NET中的一个任务)来使用忙等待,但如果是这样,我想知道它 Sleep s per loop(因为Sleep(0)会提升我的cpu风扇)。

以下是我假设它看起来如何的代码:

HANDLE hOutputRead;
typedef void (*UserCallback)(size_t);
UserCallback OutputDataReceived;
void *Buffer;

bool exec(UserCallback callback, void *buffer /* string written to stdout */)
{
    OutputDataReceived = callback;
    Buffer = buffer;

    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    HANDLE hOutputReadTemp, hOutputWrite;

    CreatePipe(&hOutputReadTemp, &hOutputWrite, &sa, 0);

    DuplicateHandle(
        GetCurrentProcess(), hOutputReadTemp,
        GetCurrentProcess(), hOutputRead,
        0, FALSE, DUPLICATE_SAME_ACCESS
    )   // to prevent hOutputReadTemp from being inherited to the launched process, 
        // we duplicate to hOutputRead with no inheritance priviledge, 
    CloseHandle(hOutputReadTemp);   // and close the original.

    STARTUPINFO si = {};
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdOutput = hOutputWrite;

    PROCESS_INFORMATION pi;
    if (!CreateProcess(NULL, "C:\\path\\to\\child.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
        return false;

    CloseHandle(pi.hThread);
    CloseHandle(hOutputWrite);  // we won't be using this handle anymore

    CreateThread(NULL, 0, CheckPipeAsync, NULL, 0, NULL);
}

DWORD WINAPI CheckPipeAsync(LPVOID lpParameter) // if anything gets written to output, call OutputDataReceived()
{
    int size;

    while (PeekNamedPipe(hOutputRead, NULL, NULL, NULL, &size, NULL))  // busy wait
    {
        if (size == 0) // nothing written
        {
            Sleep(TIME_TO_SLEEP_PER_LOOP);
            continue;
        }

        DWORD bytesRead;
        ReadFile(hOutputRead, Buffer, size, &bytesRead, NULL);
        OutputDataReceived(size);   // callback when something was written to stdout
    }

    return TRUE;
}

reference (How to spawn console processes with redirected standard handles)

请原谅我可怜的英语。

0 个答案:

没有答案