WinExec
int main() {
WinExec("E:\\MyToolBar\\Programming\\取色器.exe", SW_SHOWNORMAL); cout << "取色器 GetLastError = " << GetLastError() << endl; WinExec("D:\\MyFiles\\WeGame\\tgp_daemon.exe", SW_SHOWNORMAL); cout << "tgp_daemon GetLastError = " << GetLastError() << endl; WinExec("C:\\Windows\\SysNative\\calc.exe", SW_SHOWNORMAL); cout << "calc GetLastError = " << GetLastError() << endl;
getchar(); return 0; }
|
ShellExecute ShellExecute 在不使用管理员权限运行 VS2019 的情况下仍然可以正常打开任何程序,不报 740 错误。
int main() {
ShellExecute( NULL, L"open", L"E:\\MyToolBar\\Programming\\取色器.exe", NULL, NULL, SW_SHOWNORMAL ); cout << "取色器 GetLastError = " << GetLastError() << endl;
ShellExecute(NULL,L"open",L"D:\\MyFiles\\WeGame\\tgp_daemon.exe",NULL,NULL,SW_SHOWNORMAL); cout << "tgp_daemon GetLastError = " << GetLastError() << endl;
ShellExecute(NULL, L"open", L"C:\\Windows\\SysNative\\calc.exe", NULL, NULL, SW_SHOWNORMAL); cout << "calc GetLastError = " << GetLastError() << endl;
getchar(); return 0; }
|
ShellExecuteEX 与 ShellExecute 一样,ShellExecuteEX 也不需要管理员启动就可以打开所有进程
int main() {
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO)); sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.lpFile = L"E:\\MyToolBar\\Programming\\取色器.exe"; ShellExecuteEx(&sei); cout << "取色器 GetLastError = " << GetLastError() << endl;
sei.lpFile = L"D:\\MyFiles\\WeGame\\tgp_daemon.exe"; ShellExecuteEx(&sei); cout << "tgp_daemon GetLastError = " << GetLastError() << endl;
sei.lpFile = L"C:\\Windows\\SysNative\\calc.exe"; ShellExecuteEx(&sei); cout << "calc GetLastError = " << GetLastError() << endl;
getchar(); return 0; }
|
CreateProcess 这个函数启动外部程序可以说是一波三折,首先,先看下 ASCII 或者叫 UTF-8:

int main() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi));
BOOL bRet = CreateProcess( NULL, "E:\\MyToolBar\\Programming\\取色器.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi );if(!bRet){cout << "取色器 GetLastError = " << GetLastError() << endl; }
getchar(); return 0; }
|
正常打开,没有什么问题
下面再看 Unicode 编码,仍然用上面的代码,运行一下,发现程序在调用 CreateProcess 的时候触发了空指针异常:

将代码改成如下:
int main() { WCHAR* szCommandLine = L"E:\\MyToolBar\\Programming\\取色器.exe"; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi));
BOOL bRet = CreateProcess( NULL, szCommandLine , NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi );if(!bRet){cout << "取色器 GetLastError = " << GetLastError() << endl; }
getchar(); return 0; }
|
发现异常仍然存在:

看下 MSDN 的介绍,发现 CreateProcess 的第二个参数有一句这么写到:

也就是说 CreateProcessW 的第二个参数不能是一个常量字符串,或者是一个指向只读地址的指针,这么也就说通了,因为L"E:\\MyToolBar\\Programming\\取色器.exe"
是常量字符串,WCHAR* szCommandLine = L"E:\\MyToolBar\\Programming\\取色器.exe";
是一个指针,那么最后验证一下它指向的是否是一个只读内存就可以了。
我使用 CE 验证的,通过勾选和不勾选 “可写”,可以发现 WCHAR* szCommandLine
的确是只读变量(指针):


既然这样我们只能修改代码:
int main() { WCHAR szCommandLine[] = L"E:\\MyToolBar\\Programming\\取色器.exe"; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi));
BOOL bRet = CreateProcess( NULL, szCommandLine , NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi );if(!bRet){cout << "取色器 GetLastError = " << GetLastError() << endl; }
getchar(); return 0; }
|
然后就可以正常运行了:

最后介绍下这两个结构体:
typedef struct _STARTUPINFO { DWORD cb; LPWSTR lpReserved; LPWSTR lpDesktop; LPWSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } STARTUPINFO, *LPSTARTUPINFO;
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
|