打開一個程序和創(chuàng)建一個進(jìn)程基本上是同一個意思。我們的工具箱里面有幾個函數(shù)備選:
system, WinExec, ShellExecuteEx, CreateProcess,他們有以下幾點(diǎn)不同:
- 只有system是同步操作。
- 只有ShellExecuteEx, CreateProcess支持Unicode。
- 是否打開新的Console窗口: 只在父子都是console下有效
system,WinExec總是不會打開。ShellExecuteEx,CreateProcess則可以控制是否打開新Console窗口
- 是否顯示:在父子至少有一個不是console的情況下有效。
[system]
system是在簡單的可憐,只需傳入一個命令行。
system( "notepad C://boot.ini" );
[WinExec]
WinExec比之system能夠控制目標(biāo)窗口顯示與否。
WinExec( "notepad C://boot.ini", SW_SHOW );
WinExec( "/"C://WINDOWS//system32//notepad.exe/" C://boot.ini", SW_HIDE );
cout << "xx" << endl;
WinExec( "taskkill", SW_HIDE );
cout << "xx" << endl; // 這個xx會先于taskkill的內(nèi)容顯示(因?yàn)閯?chuàng)建進(jìn)程是異步的,并且不會很快)
[ShellExecuteEx]
WinExec最大的缺陷是不支持寬字符,你無法找到WinExecW。另外你無法針對你打開的程序做進(jìn)一步的操作,比如等待程序結(jié)束等。
如果你有這些需要,就應(yīng)該使用ShellExecuteEx。
需要做的配置一個SHELLEXECUTEINFO結(jié)構(gòu),該結(jié)構(gòu)描述如何打開以及打開什么樣的程序。然后以ShellExecuteEx調(diào)用之。
SHELLEXECUTEINFO info;
ZeroMemory( &info, sizeof( info ) );
info.cbSize = sizeof( info );
// SEE_MASK_NOCLOSEPROCESS代表需要返回進(jìn)程Handle
// SEE_MASK_NO_CONSOLE只在父子都是console時有作用,表示不要產(chǎn)生新的console窗口。
info.fMask = SEE_MASK_NOCLOSEPROCESS |SEE_MASK_NO_CONSOLE;
info.lpFile = _T( "notepad" ); // 注意如果沒有提供路徑則按下列順序搜索文件(當(dāng)前目錄,系統(tǒng)目錄,注意不包括環(huán)境變量path中的目錄)
info.lpParameters = _T( "C://boot.ini" );
info.nShow = SW_SHOW;
ShellExecuteEx( &info );
// 可以進(jìn)程Handle做些事情,最常見的就是等待進(jìn)程結(jié)束。
WaitForSingleObject( info.hProcess, INFINITE );
[CreateProcess]
提供了比ShellExecuteEx更為精細(xì)的參數(shù)控制。
通常使用CreateProcess需要提供至關(guān)重要的4個參數(shù)
- cmdLine
- creationFlag
- startupInfo
- processInfo
* cmdLine是你需要呼叫之process的命令行參數(shù),比如要打開D:/test.txt, 你可以提供"notepad D://test.txt";
值得注意的是Unicode版本的CreateProcessW要求cmdLine不能是const
* creationFlag決定如何產(chǎn)生目標(biāo)process
creationFlag = CREATE_NEW_CONSOLE 將在新的console產(chǎn)生process
creationFlag = CREATE_NO_WINDOW 將在后臺產(chǎn)生process
* startupInfo決定產(chǎn)生的process的其實(shí)信息,通常我們會設(shè)置產(chǎn)生process時是否顯示窗口,這樣做:
startupInfo.dwFlags = STARTIF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_SHOW; // SW_HIDE(表示在后臺運(yùn)作,與creationFlag呼應(yīng))
* processInfo則是個輸出參數(shù),目標(biāo)進(jìn)程創(chuàng)建成功后,此輸出參數(shù)將包含進(jìn)程相關(guān)信息。
下面是一個典型的示例
HANDLE ExecuteFile( const CString& fileName, const CString& arguments,
DWORD showWindowOption,
const CString& windowTitle )
{
DWORD creationFlag = 0;
STARTUPINFO startupInfo;
ZeroMemory( &startupInfo, sizeof( startupInfo ) );
startupInfo.cb = sizeof( startupInfo );
startupInfo.dwFlags = STARTF_USESHOWWINDOW; // 使特定成員有效
startupInfo.wShowWindow = ( WORD )showWindowOption;
startupInfo.lpTitle = const_cast< LPWSTR >( windowTitle.GetString() );
CString commandLine = fileName + _T( " " ) + arguments;
PROCESS_INFORMATION processInfo;
CreateProcess(
NULL,
const_cast< LPWSTR >( commandLine.GetString() ),
NULL,
NULL,
false,
creationFlag,
NULL,
NULL,
&startupInfo,
&processInfo
);
return processInfo.hProcess;
}
可以在創(chuàng)建進(jìn)程后通過WaitForSingleObject來捕捉核心對象hProcess
當(dāng)進(jìn)程結(jié)束后,WaitForSingleObject(hProcess, INFINITE)返回。
當(dāng)然你可以WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0來立刻檢測進(jìn)程是否結(jié)束。
最后一定要CloseHandle( hProcess ) 關(guān)閉進(jìn)程句柄