如何从CreateProcess创建的子进程中获取返回数据?
从CreateProcess启动的子进程回传指定值的实用方案
嘿,针对你用CreateProcess启动调用DLL的控制台子进程后要回传指定值的需求,我给你整理几个Windows平台下实用的方案,你可以根据自己的场景挑最合适的:
1. 用进程退出码传递简单数值
这是最轻量化的方案,适合传递状态码、小整数这类简单值。子进程通过ExitProcess()或者main()函数返回值来设定退出码,父进程用GetExitCodeProcess()获取。
父进程示例代码:
#include <windows.h> #include <stdio.h> int main() { PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof(si) }; // 启动子进程 CreateProcess(NULL, L"child.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); // 等待子进程执行完毕 WaitForSingleObject(pi.hProcess, INFINITE); // 获取退出码 DWORD exitCode; GetExitCodeProcess(pi.hProcess, &exitCode); printf("子进程返回的数值:%lu\n", exitCode); // 清理句柄 CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return 0; }
子进程示例代码:
#include <windows.h> #include <stdio.h> // 假设从DLL获取的指定值 int get_value_from_dll() { return 42; // 替换成你的DLL逻辑 } int main() { int result = get_value_from_dll(); // 用ExitProcess或者直接return都可以 ExitProcess(result); // return result; }
注意:退出码是DWORD类型,范围是0到4294967295,只适合传递简单数值,没法传字符串或复杂结构。
2. 重定向标准输出/错误流传递文本数据
如果要回传字符串、日志或者格式化文本,重定向子进程的stdout/stderr到匿名管道是个不错的选择。父进程通过管道读取子进程的输出内容。
父进程示例代码:
#include <windows.h> #include <stdio.h> int main() { HANDLE hReadPipe, hWritePipe; SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE }; // 允许句柄继承 // 创建匿名管道 if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { printf("CreatePipe failed\n"); return 1; } STARTUPINFO si = { sizeof(si) }; si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = hWritePipe; // 把子进程的stdout指向管道写端 si.hStdError = hWritePipe; // 把stderr也重定向过去(可选) PROCESS_INFORMATION pi; // 启动子进程,注意要允许句柄继承 CreateProcess(NULL, L"child.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); // 父进程不需要写端,关闭它避免管道无法结束 CloseHandle(hWritePipe); // 读取子进程的输出 char buffer[1024]; DWORD bytesRead; while (ReadFile(hReadPipe, buffer, sizeof(buffer)-1, &bytesRead, NULL) && bytesRead > 0) { buffer[bytesRead] = '\0'; printf("子进程回传的文本:%s\n", buffer); } // 清理资源 CloseHandle(hReadPipe); WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return 0; }
子进程示例代码:
#include <stdio.h> // 从DLL获取文本数据 const char* get_text_from_dll() { return "这是从DLL获取的复杂文本内容"; } int main() { const char* data = get_text_from_dll(); // 直接printf到stdout,父进程就能通过管道读到 printf("%s\n", data); return 0; }
3. 用共享内存传递复杂数据结构
如果要回传大的结构体、数组这类复杂数据,共享内存是最高效的方案。父进程创建共享内存区域,把内存名称或句柄传递给子进程(比如通过命令行参数),子进程写入数据后父进程读取。
父进程示例代码:
#include <windows.h> #include <stdio.h> #include <wchar.h> #define SHARE_MEM_NAME L"MySharedMem" #define BUFFER_SIZE 1024 typedef struct { int id; char content[256]; } CustomData; int main() { // 创建共享内存 HANDLE hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // 使用系统分页文件 NULL, PAGE_READWRITE, // 可读可写权限 0, BUFFER_SIZE, SHARE_MEM_NAME); if (hMapFile == NULL) { printf("CreateFileMapping failed\n"); return 1; } // 映射内存视图到当前进程地址空间 LPVOID pBuf = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFFER_SIZE); if (pBuf == NULL) { printf("MapViewOfFile failed\n"); CloseHandle(hMapFile); return 1; } // 构造命令行,把共享内存名称传给子进程 wchar_t cmdLine[256]; swprintf(cmdLine, L"child.exe %s", SHARE_MEM_NAME); PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof(si) }; CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); // 等待子进程写入数据 WaitForSingleObject(pi.hProcess, INFINITE); // 读取共享内存里的自定义结构体 CustomData* data = (CustomData*)pBuf; printf("子进程回传的结构体:id=%d, content=%s\n", data->id, data->content); // 清理资源 UnmapViewOfFile(pBuf); CloseHandle(hMapFile); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return 0; }
子进程示例代码:
#include <windows.h> #include <stdio.h> #include <wchar.h> #include <string.h> typedef struct { int id; char content[256]; } CustomData; // 从DLL获取复杂数据 CustomData get_struct_from_dll() { CustomData data; data.id = 1001; strcpy(data.content, "来自DLL的自定义结构体数据"); return data; } int main(int argc, wchar_t* argv[]) { if (argc < 2) { printf("缺少共享内存名称参数\n"); return 1; } // 打开父进程创建的共享内存 HANDLE hMapFile = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, argv[1]); if (hMapFile == NULL) { printf("OpenFileMapping failed\n"); return 1; } // 映射内存视图 LPVOID pBuf = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (pBuf == NULL) { printf("MapViewOfFile failed\n"); CloseHandle(hMapFile); return 1; } // 写入从DLL获取的数据 CustomData data = get_struct_from_dll(); memcpy(pBuf, &data, sizeof(CustomData)); // 清理资源 UnmapViewOfFile(pBuf); CloseHandle(hMapFile); return 0; }
额外提示
如果需要同步读写(比如父进程要实时监控子进程的数据更新),可以配合**互斥体(Mutex)或事件(Event)**来实现,避免数据竞争。
内容的提问来源于stack exchange,提问作者Ruben
相关产品推荐
相关产品推荐

