You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:01:07