使用CreateProcess重定向输出到命名管道时ReadFile返回233的问题
问题描述
尝试通过CreateProcess执行命令,将STDOUT重定向到本地服务器创建的命名管道,客户端连接管道接收输出,但客户端调用ReadFile时返回错误码233(ERROR_PIPE_NOT_CONNECTED)。
服务器端代码
命名管道创建代码
char pipeunc[MAX_PATH]; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; // Setup DACL for NamedPipe InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); SetSecurityDescriptorControl(&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED); sa = { sizeof(sa), &sd, FALSE }; sprintf(pipeunc, "\\\\.\\pipe\\%s", pipename); // Create the named-pipe HANDLE pipe = CreateNamedPipeA( pipeunc, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, &sa ); if (pipe == NULL) { fprintf(fd, "Error: CreateNamedPipeA: %d\n", GetLastError()); return NULL; }
CreateProcess重定向代码
HANDLE pipeh; STARTUPINFOA sinfo; PROCESS_INFORMATION pinfo; bool res; pipeh = remote::SetupNamedPipe(pipe_name, fd); memset(&sinfo, 0, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); sinfo.dwFlags |= STARTF_USESTDHANDLES; sinfo.hStdOutput = sinfo.hStdError = pipeh; // Redirect output to named-pipe // Wait until client connects. ConnectNamedPipe(pipeh, NULL); SetHandleInformation(pipeh, HANDLE_FLAG_INHERIT, 0); res = CreateProcessA( NULL, const_cast<LPSTR>(cmd), NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo );
客户端代码
连接命名管道代码
static HANDLE pipeh; // Create a handle to the remote pipe pipeh = CreateFileA( const_cast<LPCSTR>(PipeName), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
ReadFile读取代码
while(1){ res = ReadFile( pipeh_read, // is the same handle(pipeh) buf, PIPE_MAX_READ_SIZE, NULL, NULL ); printf("%s\n", buf); if (!res) { puts("Process returned."); #ifdef DEBUG printf("ReadFile code: %d\n", GetLastError()); #endif return; } }
错误码233(ERROR_PIPE_NOT_CONNECTED)原因及修复方案
错误码233表示管道连接已断开或未正确建立,以下是核心问题和修复步骤:
管道句柄继承标志设置时机错误:
服务器端在ConnectNamedPipe后立即取消句柄继承属性,导致CreateProcess无法将句柄传递给子进程,子进程写入管道失败,连接断开。
修复:将SetHandleInformation移至CreateProcess之后执行,确保子进程已继承句柄:res = CreateProcessA(...); if (res) { SetHandleInformation(pipeh, HANDLE_FLAG_INHERIT, 0); WaitForSingleObject(pinfo.hProcess, INFINITE); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); CloseHandle(pipeh); }未检查ConnectNamedPipe返回值:
ConnectNamedPipe可能因客户端连接异常失败,未处理会导致后续操作使用无效句柄。
修复:添加返回值检查:BOOL connectResult = ConnectNamedPipe(pipeh, NULL); if (!connectResult && GetLastError() != ERROR_PIPE_CONNECTED) { fprintf(fd, "Error: ConnectNamedPipe: %d\n", GetLastError()); CloseHandle(pipeh); return NULL; }ReadFile未传递字节数指针:
消息类型管道需要获取实际读取字节数,否则无法正确终止字符串,引发读取逻辑错误。
修复:修改ReadFile调用,传入字节数变量并添加字符串终止符:DWORD bytesRead; while(1){ res = ReadFile( pipeh, buf, PIPE_MAX_READ_SIZE - 1, &bytesRead, NULL ); if (!res) { DWORD err = GetLastError(); err == ERROR_BROKEN_PIPE ? puts("Pipe closed by server.") : printf("ReadFile error: %d\n", err); return; } buf[bytesRead] = '\0'; printf("%s\n", buf); }未正确关闭服务器端管道句柄:
子进程退出后未关闭管道句柄,客户端无法感知连接断开,引发233错误。
修复:子进程退出后关闭管道句柄:WaitForSingleObject(pinfo.hProcess, INFINITE); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); CloseHandle(pipeh);客户端未检查CreateFile返回值:
客户端未验证管道连接是否成功,若CreateFile失败,后续ReadFile使用无效句柄导致错误。
修复:添加连接检查:pipeh = CreateFileA(...); if (pipeh == INVALID_HANDLE_VALUE) { printf("Failed to connect pipe: %d\n", GetLastError()); return; }
内容的提问来源于stack exchange,提问作者zbx0310
相关产品推荐
相关产品推荐

