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