Windows下如何用C/C++编写程序执行外部程序并接收其返回信息?
Windows下C++实现子进程启动与进程间通信
你的需求完全可以通过C/C++实现,Windows平台下最适合这个场景的方案是匿名管道(Anonymous Pipe),它能让父进程(程序1)和子进程(程序2)之间单向传递数据,刚好匹配「程序1启动程序2,程序2发数据给程序1后退出」的流程。
核心实现思路
- 父进程创建一对匿名管道:一端用于读取子进程的输出,另一端让子进程写入数据
- 父进程通过
CreateProcess启动子进程,将子进程的标准输出重定向到管道的写入端 - 子进程启动后,直接向标准输出(
stdout)写入要传递的信息,随后退出 - 父进程从管道的读取端读取子进程发送的数据,完成通信
代码示例
父进程(程序1)代码
#include <windows.h> #include <iostream> #include <string> int main() { HANDLE hReadPipe, hWritePipe; SECURITY_ATTRIBUTES sa = {0}; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; // 允许子进程继承管道句柄 // 创建匿名管道 if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { std::cerr << "CreatePipe failed, error: " << GetLastError() << std::endl; return 1; } STARTUPINFO si = {0}; si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = hWritePipe; // 将子进程的stdout重定向到管道写入端 si.hStdError = hWritePipe; // 可选:把子进程的stderr也重定向过来 PROCESS_INFORMATION pi = {0}; // 启动子进程(替换为你的程序2路径,比如"./program2.exe") if (!CreateProcess( NULL, (LPSTR)"./program2.exe", NULL, NULL, TRUE, // 继承父进程的句柄 0, NULL, NULL, &si, &pi )) { std::cerr << "CreateProcess failed, error: " << GetLastError() << std::endl; CloseHandle(hReadPipe); CloseHandle(hWritePipe); return 1; } // 关闭父进程端的写入管道(子进程还持有它,不影响) CloseHandle(hWritePipe); // 读取子进程发送的数据 char buffer[1024]; DWORD bytesRead; std::string receivedData; while (ReadFile(hReadPipe, buffer, sizeof(buffer)-1, &bytesRead, NULL) && bytesRead > 0) { buffer[bytesRead] = '\0'; receivedData += buffer; } std::cout << "Received from program2: " << receivedData << std::endl; // 等待子进程退出,清理资源 WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(hReadPipe); return 0; }
子进程(程序2)代码
#include <iostream> int main() { // 直接向stdout写入要传递的信息 std::cout << "Hello from Program 2! This is the data I want to send." << std::endl; // 用fflush确保数据立即写入管道,避免缓冲 fflush(stdout); // 程序自动退出,完成流程 return 0; }
关键细节说明
- 管道继承:创建管道时
sa.bInheritHandle必须设为TRUE,同时CreateProcess的第5个参数设为TRUE,这样子进程才能继承管道句柄。 - 句柄关闭:父进程启动子进程后要立即关闭自己持有的写入管道句柄,否则读取管道的
ReadFile会一直等待,直到所有写入端都关闭。 - 数据缓冲:子进程如果用C++的
cout,可能会有缓冲,所以用fflush(stdout)强制刷新,确保数据立刻发送到管道。 - 错误处理:代码里的
GetLastError可以帮助排查创建管道或启动进程时的问题。
除了匿名管道,你也可以用命名管道、共享内存等方式,但匿名管道是这个场景下最简单高效的选择。
内容的提问来源于stack exchange,提问作者Nico Cano
相关产品推荐
相关产品推荐

