本文介绍了win32 (WinAPI) 中的断管的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循了此处的示例从管道读取,但 ReadFile 失败并且 GetLastError() 显示管道已损坏.
我已经在程序的早期创建并使用了(成功)一个管道,但我关闭了所有句柄并为新管道使用了全新的变量,只是为了确定.
任何想法为什么这不起作用?

I have followed the example here for reading from a pipe, but ReadFile fails and GetLastError() shows me that the pipe is broken.
I have created and used (successfully) a pipe earlier in the program, but I closed all the handles and used entirely new variables for the new pipe just to be sure.
Any ideas why this doesn't work?

HANDLE g_hChildStd_OUT_Rd2 = NULL;
HANDLE g_hChildStd_OUT_Wr2 = NULL;
SECURITY_ATTRIBUTES saAttr2;
STARTUPINFO si2;
PROCESS_INFORMATION pi2;

ZeroMemory( &si2, sizeof(si2) );
si2.cb = sizeof(si2);
ZeroMemory( &pi2, sizeof(pi2) );
//create pipe
saAttr2.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr2.bInheritHandle = TRUE;
saAttr2.lpSecurityDescriptor = NULL;
CreatePipe(&g_hChildStd_OUT_Rd2, &g_hChildStd_OUT_Wr2, &saAttr2, 0);
//create child process
bSuccess = FALSE;
memset(szCmdLine, 0, MAX_PATH);
sprintf(szCmdLine, "ffmpeg.exe -i output.mp3");
ZeroMemory( &pi2, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si2, sizeof(STARTUPINFO) );
si2.cb = sizeof(STARTUPINFO);
si2.hStdOutput = g_hChildStd_OUT_Wr2;
si2.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2);
//read from pipe
CloseHandle(g_hChildStd_OUT_Wr2);
memset(chBuf, 0, BUFSIZE);
for (;;)
{
  bSuccess = ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL);
  [bSuccess is 0 and GetLastError() returns error 109]
  ........

推荐答案

Broken pipe"是另一端关闭管道时的正常错误.在您的情况下,这要么意味着没有另一端",要么其他应用程序尚未向其 stdout 写入任何内容.我已将您的代码修改为可编译的测试用例 - 在两种情况下 ReadFile 失败而没有为我读取任何数据:

"Broken pipe" is a normal error when the other end closes the pipe. In your case, this either means there is no "other end", or the other application hasn't written anything to its stdout.I've modified your code to be a compilable test case – there are two cases in which ReadFile fails without having read any data for me:

  • CreateProcess 失败.我添加了一个 assert 以便可以识别该问题.这当然会导致管道破裂.
  • 该进程不会向标准输出写入任何内容.它可能会写入其标准错误流.我也将 stderr 重定向到了管道,正如我的 echo 示例所示,这将在管道的另一端接收两个流.
  • CreateProcess failed. I've added an assert so that problem will be recognizable. It would of course result in a broken pipe.
  • The process does not write anything to standard output. It might instead write to its standard error stream. I've redirected stderr to the pipe as well, and as my echo example shows, this will receive both streams on the other end of the pipe now.

代码:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

#define BUFSIZE 200

int main(void)
{
    BOOL bSuccess;
    char szCmdLine[MAX_PATH];
    char chBuf[BUFSIZE];
    DWORD dwRead;
    HANDLE g_hChildStd_OUT_Rd2 = NULL;
    HANDLE g_hChildStd_OUT_Wr2 = NULL;
    SECURITY_ATTRIBUTES saAttr2;
    STARTUPINFO si2;
    PROCESS_INFORMATION pi2;

    ZeroMemory( &si2, sizeof(si2) );
    si2.cb = sizeof(si2);
    ZeroMemory( &pi2, sizeof(pi2) );
    //create pipe
    saAttr2.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr2.bInheritHandle = TRUE;
    saAttr2.lpSecurityDescriptor = NULL;
    assert(CreatePipe(&g_hChildStd_OUT_Rd2, &g_hChildStd_OUT_Wr2, &saAttr2, 0));
    //create child process
    bSuccess = FALSE;
    memset(szCmdLine, 0, MAX_PATH);
    sprintf(szCmdLine, "cmd /c echo output && echo error>&2");
    ZeroMemory( &pi2, sizeof(PROCESS_INFORMATION) );
    ZeroMemory( &si2, sizeof(STARTUPINFO) );
    si2.cb = sizeof(STARTUPINFO);
    si2.hStdOutput = g_hChildStd_OUT_Wr2;
    si2.hStdError = g_hChildStd_OUT_Wr2; // also add the pipe as stderr!
    si2.dwFlags |= STARTF_USESTDHANDLES;
    assert(CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2));
    //read from pipe
    CloseHandle(g_hChildStd_OUT_Wr2);
    memset(chBuf, 0, BUFSIZE);
    for (;;)
    {
        bSuccess = ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL);
        printf("%d %lu 0x%08lx\n", bSuccess, dwRead, GetLastError());
        if (bSuccess)
            printf("\t'%*s'\n", (int)dwRead, chBuf);
        else
            break;
    }
    return 0;
}

这篇关于win32 (WinAPI) 中的断管的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 12:45
查看更多