AI生成,由我提问
CreateProcess 和 ShellExecute 函数详解
这两个Windows API函数都用于创建进程或执行程序,但功能和用法有显著区别。
一、CreateProcess 函数
1. 函数原型
BOOL CreateProcess(
LPCTSTR lpApplicationName, // 可执行文件名称
LPTSTR lpCommandLine, // 命令行参数
LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性
BOOL bInheritHandles, // 句柄继承标志
DWORD dwCreationFlags, // 创建标志
LPVOID lpEnvironment, // 环境变量
LPCTSTR lpCurrentDirectory, // 当前目录
LPSTARTUPINFO lpStartupInfo, // 启动信息
LPPROCESS_INFORMATION lpProcessInformation // 进程信息
);2. 基本使用示例
#include <windows.h>
#include <iostream>
int main() {
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
// 创建一个记事本进程
BOOL success = CreateProcess(
L"C:\\Windows\\System32\\notepad.exe", // 应用程序路径
NULL, // 命令行参数
NULL, // 进程安全属性
NULL, // 线程安全属性
FALSE, // 不继承句柄
0, // 默认创建标志
NULL, // 使用父进程环境变量
NULL, // 使用父进程当前目录
&si, // 启动信息
&pi // 进程信息
);
if (success) {
std::wcout << L"进程创建成功!" << std::endl;
std::wcout << L"进程ID: " << pi.dwProcessId << std::endl;
std::wcout << L"线程ID: " << pi.dwThreadId << std::endl;
// 等待进程结束
WaitForSingleObject(pi.hProcess, INFINITE);
// 关闭句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else {
std::wcout << L"进程创建失败,错误码: " << GetLastError() << std::endl;
}
return 0;
}3. 高级用法示例
// 带命令行参数的创建
CreateProcess(
L"C:\\Windows\\System32\\cmd.exe",
L" /c dir C:\\", // 注意:前面需要空格
NULL, NULL, FALSE,
CREATE_NEW_CONSOLE, // 创建新控制台窗口
NULL, NULL, &si, &pi
);
// 隐藏窗口执行
STARTUPINFO si = { sizeof(si) };
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; // 隐藏窗口
CreateProcess(
L"C:\\MyApp.exe",
NULL, NULL, NULL, FALSE,
CREATE_NO_WINDOW, // 不创建窗口
NULL, NULL, &si, &pi
);二、ShellExecute 函数
1. 函数原型
HINSTANCE ShellExecute(
HWND hwnd, // 父窗口句柄
LPCTSTR lpOperation, // 操作类型 ("open", "print", "explore"等)
LPCTSTR lpFile, // 要操作的文件
LPCTSTR lpParameters,// 参数
LPCTSTR lpDirectory, // 默认目录
INT nShowCmd // 显示方式
);2. 基本使用示例
#include <windows.h>
#include <shellapi.h> // 需要包含此头文件
#include <iostream>
int main() {
// 1. 打开记事本
HINSTANCE result = ShellExecute(
NULL, // 父窗口句柄
L"open", // 操作类型
L"notepad.exe", // 程序名
NULL, // 参数
NULL, // 默认目录
SW_SHOWNORMAL // 正常显示
);
// 检查返回值(大于32表示成功)
if ((int)result > 32) {
std::wcout << L"执行成功!" << std::endl;
} else {
std::wcout << L"执行失败,错误码: " << (int)result << std::endl;
}
// 2. 打开文件(使用关联程序)
ShellExecute(NULL, L"open", L"C:\\document.txt", NULL, NULL, SW_SHOWNORMAL);
// 3. 打开网址
ShellExecute(NULL, L"open", L"https://www.example.com", NULL, NULL, SW_SHOWNORMAL);
// 4. 打印文档
ShellExecute(NULL, L"print", L"C:\\document.txt", NULL, NULL, SW_HIDE);
// 5. 浏览文件夹
ShellExecute(NULL, L"explore", L"C:\\Windows", NULL, NULL, SW_SHOWNORMAL);
// 6. 以管理员权限运行(需要UAC提示)
ShellExecute(NULL, L"runas", L"setup.exe", NULL, NULL, SW_SHOWNORMAL);
return 0;
}3. 更多用法示例
// 使用ShellExecute执行带参数的程序
ShellExecute(
NULL,
L"open",
L"cmd.exe",
L"/c dir C:\\", // 命令行参数
NULL,
SW_HIDE // 隐藏窗口
);
// 发送邮件
ShellExecute(
NULL,
L"open",
L"mailto:someone@example.com?subject=Hello&body=Test",
NULL, NULL, SW_SHOWNORMAL
);三、主要区别对比
| 特性 | CreateProcess | ShellExecute |
|---|---|---|
| 用途 | 专门创建进程 | 执行文件操作、打开文档、运行程序 |
| 功能范围 | 只能执行可执行文件 | 可以打开任意文件(使用关联程序) |
| 灵活性 | 高度可控,可设置进程属性 | 简单易用,但控制较少 |
| 返回值 | 详细的进程信息 | 简单成功/失败指示 |
| 权限控制 | 可使用进程安全属性 | 支持runas提权 |
| 资源消耗 | 较高 | 较低 |
| 异步/同步 | 可同步等待进程结束 | 默认异步 |
四、选择建议
使用 CreateProcess 的场景:
- 需要获取进程句柄和线程句柄
- 需要精确控制进程创建过程
- 需要设置进程优先级、创建标志等
- 需要等待进程结束
- 执行控制台程序并需要获取输出
使用 ShellExecute 的场景:
- 快速运行程序或打开文档
- 需要使用文件关联(如打开.txt文件用记事本)
- 打开网址、邮件、文件夹等
- 需要以管理员权限运行(runas)
- 不需要详细的进程控制
五、综合示例
// 一个更完整的比较示例
#include <windows.h>
#include <shellapi.h>
#include <iostream>
#include <string>
// 使用CreateProcess执行并等待
bool RunWithCreateProcess(const std::wstring& appPath, const std::wstring& args) {
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
std::wstring cmdLine = L"\"" + appPath + L"\" " + args;
if (CreateProcess(NULL, &cmdLine[0], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE); // 等待完成
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
std::wcout << L"CreateProcess: 退出码 = " << exitCode << std::endl;
return true;
}
return false;
}
// 使用ShellExecute执行(异步)
bool RunWithShellExecute(const std::wstring& operation, const std::wstring& file) {
HINSTANCE result = ShellExecute(NULL, operation.c_str(), file.c_str(), NULL, NULL, SW_SHOWNORMAL);
return ((int)result > 32);
}
int main() {
// 使用CreateProcess运行命令并等待
RunWithCreateProcess(L"C:\\Windows\\System32\\cmd.exe", L"/c dir C:\\ > c:\\dir.txt");
// 使用ShellExecute打开文本文件
RunWithShellExecute(L"open", L"C:\\dir.txt");
// 使用ShellExecute打开网址
RunWithShellExecute(L"open", L"https://www.example.com");
return 0;
}这两个函数各有优势,根据具体需求选择合适的函数可以提高开发效率。