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

如何向WinAPI的CreateProcess传递非字符串类型的多参数

用WinAPI CreateProcess传递非字符串参数(内存指针/数值)并支持修改的实现方案

你当前的方法无法生效的核心原因有两个:

  1. CreateProcessW的命令行参数仅支持字符串类型,直接传递结构体指针会被当作字符串解析,必然出错。
  2. Windows进程拥有独立的地址空间,父进程的内存指针在子进程中是无效的,无法直接访问。

以下是几种可行的实现方案,均支持子进程修改数据:

方案一:使用共享内存(File Mapping)

共享内存是跨进程共享数据的标准方案,父进程创建一块命名的共享内存区域,写入参数数据;子进程通过名称打开这块共享内存,读取并修改数据,修改结果会直接同步到父进程。

父进程代码

#include <windows.h>
#include <swprintf.h>

struct Arguments {
    void* ptr;  // 若要让子进程访问父进程内存,需先将该内存也转为共享内存
    int value;
} Arg;

int main() {
    Arg.value = 1337;
    Arg.ptr = NULL;  // 示例仅传递数值,若需传递可访问内存需额外处理

    // 创建共享内存,大小刚好容纳Arguments结构体
    HANDLE hMapFile = CreateFileMappingW(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        sizeof(Arguments),
        L"MySharedArgs");

    if (hMapFile == NULL) return GetLastError();

    // 将共享内存映射到父进程地址空间
    Arguments* pSharedArgs = (Arguments*)MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        sizeof(Arguments));

    if (pSharedArgs == NULL) {
        CloseHandle(hMapFile);
        return GetLastError();
    }

    // 将参数写入共享内存
    *pSharedArgs = Arg;

    // 启动子进程,将共享内存名称作为命令行参数传递
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    wchar_t cmdLine[256];
    swprintf_s(cmdLine, L"\"...\\Injet x86.exe\" MySharedArgs");

    if (!CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        UnmapViewOfFile(pSharedArgs);
        CloseHandle(hMapFile);
        return GetLastError();
    }

    // 等待子进程结束,读取修改后的参数
    WaitForSingleObject(pi.hProcess, INFINITE);
    Arg = *pSharedArgs;

    // 清理资源
    UnmapViewOfFile(pSharedArgs);
    CloseHandle(hMapFile);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

子进程代码(无默认库)

#include <windows.h>

struct Arguments {
    void* ptr;
    int value;
};

void WINAPI WinMainCRTStartup() {
    // 获取命令行中的共享内存名称
    wchar_t* cmdLine = GetCommandLineW();
    // 跳过程序名,定位到共享内存名称
    while (*cmdLine != L' ' && *cmdLine != L'\0') cmdLine++;
    if (*cmdLine == L' ') cmdLine++;

    // 打开共享内存
    HANDLE hMapFile = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, cmdLine);
    if (hMapFile == NULL) ExitProcess(GetLastError());

    // 将共享内存映射到子进程地址空间
    Arguments* pArgs = (Arguments*)MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        sizeof(Arguments));

    if (pArgs == NULL) {
        CloseHandle(hMapFile);
        ExitProcess(GetLastError());
    }

    // 修改参数数据(会同步到父进程的共享内存)
    pArgs->value = 42;

    // 清理资源
    UnmapViewOfFile(pArgs);
    CloseHandle(hMapFile);

    ExitProcess(0);
}

方案二:使用WriteProcessMemory写入子进程内存

父进程先以暂停状态启动子进程,在子进程地址空间分配内存并写入参数,再通过共享内存传递该内存的地址,最后恢复子进程运行。子进程读取地址后直接访问自己地址空间内的参数并修改。

父进程代码

#include <windows.h>

struct Arguments {
    void* ptr;
    int value;
} Arg;

int main() {
    Arg.value = 1337;
    Arg.ptr = NULL;

    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    // 以暂停状态启动子进程
    if (!CreateProcessW(
        L"...\\Injet x86.exe",
        NULL,
        NULL,
        NULL,
        FALSE,
        CREATE_SUSPENDED,
        NULL,
        NULL,
        &si,
        &pi)) {
        return GetLastError();
    }

    // 在子进程地址空间分配内存
    Arguments* pRemoteArgs = (Arguments*)VirtualAllocEx(
        pi.hProcess,
        NULL,
        sizeof(Arguments),
        MEM_COMMIT | MEM_RESERVE,
        PAGE_READWRITE);

    if (pRemoteArgs == NULL) {
        TerminateProcess(pi.hProcess, -1);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return GetLastError();
    }

    // 将参数写入子进程内存
    if (!WriteProcessMemory(pi.hProcess, pRemoteArgs, &Arg, sizeof(Arguments), NULL)) {
        VirtualFreeEx(pi.hProcess, pRemoteArgs, 0, MEM_RELEASE);
        TerminateProcess(pi.hProcess, -1);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return GetLastError();
    }

    // 创建共享内存传递子进程内的参数地址
    HANDLE hMapAddr = CreateFileMappingW(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        sizeof(void*),
        L"MyArgAddr");

    if (hMapAddr != NULL) {
        void** pSharedAddr = (void**)MapViewOfFile(hMapAddr, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(void*));
        if (pSharedAddr != NULL) {
            *pSharedAddr = pRemoteArgs;
            UnmapViewOfFile(pSharedAddr);
        }
        CloseHandle(hMapAddr);
    }

    // 恢复子进程运行
    ResumeThread(pi.hThread);

    // 等待子进程结束,读取修改后的参数
    WaitForSingleObject(pi.hProcess, INFINITE);
    Arguments modifiedArg;
    ReadProcessMemory(pi.hProcess, pRemoteArgs, &modifiedArg, sizeof(Arguments), NULL);

    // 清理资源
    VirtualFreeEx(pi.hProcess, pRemoteArgs, 0, MEM_RELEASE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

子进程代码(无默认库)

#include <windows.h>

struct Arguments {
    void* ptr;
    int value;
};

void WINAPI WinMainCRTStartup() {
    // 打开存储参数地址的共享内存
    HANDLE hMapAddr = OpenFileMappingW(FILE_MAP_READ, FALSE, L"MyArgAddr");
    if (hMapAddr == NULL) ExitProcess(GetLastError());

    void** pRemoteArgsAddr = (void**)MapViewOfFile(
        hMapAddr,
        FILE_MAP_READ,
        0,
        0,
        sizeof(void*));

    if (pRemoteArgsAddr == NULL) {
        CloseHandle(hMapAddr);
        ExitProcess(GetLastError());
    }

    // 获取子进程内的参数地址
    Arguments* pArgs = (Arguments*)*pRemoteArgsAddr;

    // 修改参数数据
    pArgs->value = 42;

    // 清理资源
    UnmapViewOfFile(pRemoteArgsAddr);
    CloseHandle(hMapAddr);

    ExitProcess(0);
}

关键注意事项

  • 地址空间隔离:父进程的内存指针无法直接在子进程中使用,必须通过共享内存或WriteProcessMemory将数据转移到子进程可访问的空间。
  • 数据修改同步:使用共享内存时,子进程的修改会直接同步到父进程;使用WriteProcessMemory方案时,父进程需要主动读取子进程内存来获取修改后的数据。
  • 资源清理:所有创建的句柄、映射内存都要及时关闭/释放,避免内存泄漏。

内容的提问来源于stack exchange,提问作者EnderMega

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:51:37