Win32 - 创建进程

 

1. 核心函数:CreateProcess

Windows 中创建进程的 API 是 CreateProcess。它会创建一个新进程和它的主线程,并加载指定的可执行文件。

BOOL CreateProcess(
  LPCWSTR               lpApplicationName,   // 可执行文件路径
  LPWSTR                lpCommandLine,       // 命令行参数
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全属性(通常为NULL)
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // 线程安全属性(通常为NULL)
  BOOL                  bInheritHandles,     // 句柄是否可继承
  DWORD                 dwCreationFlags,     // 创建标志(如 CREATE_NEW_CONSOLE)
  LPVOID                lpEnvironment,       // 环境变量(NULL=继承父进程)
  LPCWSTR               lpCurrentDirectory,  // 工作目录(NULL=同父进程)
  LPSTARTUPINFOW        lpStartupInfo,       // 启动信息(窗口样式等)
  LPPROCESS_INFORMATION lpProcessInformation // 返回进程/线程句柄和ID
);

重点:最后一个参数 lpProcessInformation 会返回新进程的句柄和 ID,之后可以用 WaitForSingleObject 等待进程结束,用 CloseHandle 关闭句柄。


2. 最简单的示例:启动一个记事本

#include <windows.h>
#include <stdio.h>

int main()
{
    STARTUPINFOW si = { sizeof(si) };          // 必须初始化大小
    PROCESS_INFORMATION pi = { 0 };            // 用于接收进程信息

    // 创建进程启动记事本
    BOOL success = CreateProcessW(
        L"C:\\Windows\\System32\\notepad.exe", // 应用程序路径
        NULL,                                  // 命令行参数(无额外参数)
        NULL, NULL,                            // 安全属性(默认)
        FALSE,                                 // 句柄不继承
        0,                                     // 创建标志(普通)
        NULL,                                  // 使用父进程环境变量
        NULL,                                  // 使用父进程工作目录
        &si,                                   // 启动信息
        &pi                                    // 进程信息输出
    );

    if (!success)
    {
        printf("CreateProcess failed, error code: %d\n", GetLastError());
        return 1;
    }

    printf("新进程 PID = %d\n", pi.dwProcessId);

    // 等待新进程结束(无限等待)
    WaitForSingleObject(pi.hProcess, INFINITE);
    printf("记事本已关闭,继续执行。\n");

    // 关闭句柄,避免资源泄露
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

编译运行
用 cl /EHsc CreateProcessDemo.cpp 编译,然后执行。会打开记事本,等你关闭记事本后,控制台才会打印结束信息。


3. 带命令行参数的示例:启动自己的程序

假设当前目录下有一个 SemaphoreSignal.exe 需要启动(不需要传参数时可直接在 lpCommandLine 中写 NULL),如果需要传参数,则必须使用可写的缓冲区,且 lpApplicationName 可以设为 NULL

#include <windows.h>
#include <stdio.h>

int main()
{
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = { 0 };

    // 命令行字符串(必须可修改,所以用数组)
    wchar_t cmdLine[] = L"SemaphoreSignal.exe";

    BOOL success = CreateProcessW(
        NULL,          // 使用命令行中的可执行文件名称
        cmdLine,       // 命令行(可包含参数,例如 L"SemaphoreSignal.exe arg1 arg2")
        NULL, NULL,
        FALSE,
        0,
        NULL, NULL,
        &si,
        &pi
    );

    if (!success)
    {
        printf("CreateProcess failed, error: %d\n", GetLastError());
        return 1;
    }

    // 可选:等待子进程结束
    WaitForSingleObject(pi.hProcess, INFINITE);
    printf("子进程已退出。\n");

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
}

注意

  • lpCommandLine 必须是一个可写的缓冲区,不能是字符串常量(如 L"..."),因为 CreateProcess 可能会修改它。

  • 如果可执行文件不在当前目录或系统 PATH 中,应给出完整路径,或在 lpApplicationName 中指定完整路径。


4. 常用创建标志 (dwCreationFlags)

 
标志 作用
CREATE_NEW_CONSOLE 新进程创建一个新控制台窗口(而非继承父进程的控制台)
CREATE_NO_WINDOW 不创建窗口(用于后台进程)
DEBUG_PROCESS 调试新进程
CREATE_SUSPENDED 主线程挂起,需手动调用 ResumeThread

示例:启动一个带新控制台窗口的程序:

CreateProcessW(..., CREATE_NEW_CONSOLE, ...);

5. 获取进程退出码

可以用 GetExitCodeProcess 获得进程的返回值(即 main 或 WinMain 的返回值):

DWORD exitCode;
if (GetExitCodeProcess(pi.hProcess, &exitCode))
    printf("子进程退出码: %d\n", exitCode);

6. 注意事项

  • 必须关闭句柄pi.hProcess 和 pi.hThread 即使进程已结束,也必须调用 CloseHandle 释放内核对象引用计数。

  • 缓冲区生命周期lpCommandLine 指向的内存必须保证在 CreateProcess 调用期间有效,且不要被提前释放。

  • 路径空格:如果可执行文件路径包含空格,必须用双引号括起来,并且要将整个路径放在 lpApplicationName 中,或者使用 lpCommandLine 时也加上引号。

     
    CreateProcessW(L"\"C:\\Program Files\\MyApp\\app.exe\"", NULL, ...);
  • 继承句柄:若 bInheritHandles = TRUE,子进程会继承父进程的可继承的句柄(如文件映射、信号量等),使用时需小心,避免意外共享。


7. 完整示例:启动 SemaphoreSignal.exe 并等待

结合之前信号量的例子,你可以在 SemaphoreWait.exe 中创建一个子进程来运行 SemaphoreSignal.exe,自动释放信号量。

// 在 SemaphoreWait.cpp 中,获得信号量后可以创建子进程释放它
// 仅作演示,实际业务中不这么用

STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
wchar_t cmd[] = L"SemaphoreSignal.exe";

CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE); // 等待信号量释放程序执行完毕
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

 

posted @ 2026-06-12 14:49  [BORUTO]  阅读(17)  评论(0)    收藏  举报