C++小知識(八)——C/C++執行外部程式(呼叫外部exe程式)
轉載自:https://blog.csdn.net/dongpanshan/article/details/7835722,其中我只用到了ShellExecute函式,根據下面的示例以及介紹的其中的引數進行了調整,實現了對外部exe的呼叫
C中的函式:
1.exec() 函式家族:
exec() 家族的函式將會建立一個新的程序來執行程式。(不能設定許可權,只是單純的傳值執行exe)
_execl, _wexecl
_execv, _wexecv
_execle, _wexecle
_execve, _wexecve
_execlp, _wexeclp
_execvp, _wexecvp
_execlpe, _wexeclpe
_execvpe, _wexecvpe
具體使用例子msdn:ms-help://MS.MSDNQTR.v90.chs/dv_vccrt/html/a261df93-206a-4fdc-b8ac-66aa7db83bc6.htm
2.spawn()函式家族:
spawn() 家族的函式將會建立一個新的程序來執行程式。(不能設定許可權,只是單純的傳值執行exe)
_spawnl, _wspawnl
_spawnv, _wspawnv
_spawnle, _wspawnle
_spawnve, _wspawnve
_spawnlp, _wspawnlp
_spawnvp, _wspawnvp
_spawnlpe, _wspawnlpe
_spawnvpe, _wspawnvpe
具體使用例子msdn:ms-help://MS.MSDNQTR.v90.chs/dv_vccrt/html/bb47c703-5216-4e09-8023-8cf25bbf2cf9.htm
3.system()函式
可用於執行控制檯命令(DOS命令),比如 system("cls");//清屏,等於在DOS上使用cls命令
WIN32 API
1.WinExec()函式
只提供16位windows程式使用。(不能設定許可權,只是單純的傳值執行exe)
⑴ 函式原型: UINT Win Exec(LPCSTR lpCmdLine, UINT uCmdShow); ⑵ 引數: lpCmdLine:指向一個空結束的字串,串中包含將要執行的應用程式的命令列(檔名加上可選引數)。 uCmdShow:定義Windows應用程式的視窗如何顯示,併為CreateProcess函式提供STARTUPINFO引數的wShowWindow成員的值。 ⑶ 返回值: 若函式呼叫成功,則返回值大於31。若函式呼叫失敗,則返回值為下列之一: ① 0:系統記憶體或資源已耗盡。 ② ERROR_BAD_FORMAT:EXE檔案無效(非Win32.EXE或.EXE影像錯誤)。 ③ ERROR_FILE_NOT_FOUND:指定的檔案未找到。 ④ ERROR_PATH_NOT_FOUND:指定的路徑未找到。 雖然Microsoft認為WinExec已過時,但是在許多時候,簡單的WinExec函式仍是執行新程式的最好方式。簡單地傳送作為第一個引數的 命令列,還需要決定如何顯示程式(該程式也許會忽視它)的第二個引數。通常,將其設定為SW_SHOW,也可嘗試SW_MINIMIZED或 SW_MAXIMIZED。WinExec不允許用CreateProcess獲得的所有選項,而它的確簡單。
2.ShellExecute() 、ShellExecuteEx() 後者可以設定以管理員許可權執行(已執行)
ShellExecute不僅可以執行EXE檔案,也可以執行已經關聯的檔案。
⑴標準用法 ShellExecute函式原型及引數含義如下:
HINSTANCE ShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd);
●hWnd:用於指定父視窗控制代碼。當函式呼叫過程出現錯誤時,它將作為Windows訊息視窗的父視窗。例如,可以將其設定為應用程式主視窗控制代碼,即Application.Handle,也可以將其設定為桌面視窗控制代碼(用GetDesktopWindow函式獲得)。 ●lpOperation:用於指定要進行的操作。其中“open”操作表示執行由FileName引數指定的程式,或開啟由FileName引數指定的檔案或資料夾;“print”操作表示列印由FileName引數指定的檔案;“explore”操作表示瀏覽由FileName引數指定的資料夾。當引數設為nil時,表示執行預設操作“open”。 ●lpFileName:用於指定要開啟的檔名、要執行的程式檔名或要瀏覽的資料夾名。 ●lpParameters:若FileName引數是一個可執行程式,則此引數指定命令列引數,否則此引數應為nil或PChar(0)。 ●lpDirectory:用於指定預設目錄。 ●lpShowCmd:若FileName引數是一個可執行程式,則此引數指定程式視窗的初始顯示方式,否則此引數應設定為0。
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <shellapi.h> int main( void ) { HINSTANCE hNewExe = ShellExecuteA(NULL, "open", "d:\\tese.log", NULL, NULL, SW_SHOW); if ((DWORD)hNewExe <= 32) { printf("return value:%d\n", (DWORD)hNewExe); } else { printf("successed!\n"); } printf("GetLastError: %d\n", GetLastError()); system("pause"); return 1;
}
當“D:\\test.log”檔案不存在是,執行結果如下: 這裡若函式執行錯誤, GetLastError()不一定能捕獲到錯誤程式碼,例如當“d:\\tese.log”檔案存在,將記事本"notepad.exe"命名為其他名字時:
另外兩個函式的返回值就不列出了。
(2) 特殊用法
1)如果將FileName引數設定為“http:”協議格式,那麼該函式將開啟預設瀏覽器並連結到指定的URL地址。若使用者機器中安裝了多個瀏覽器,則該函式將根據Windows 9x/NT登錄檔中http協議處理程式(Protocols Handler)的設定確定啟動哪個瀏覽器。 格式一:http://網站域名。 如:ShellExecute(handle, “open”, “http://www.neu.edu.cn”, nil, nil, SW_SHOWNORMAL); 格式二:http://網站域名/網頁檔名。 如:ShellExecute(handle, “open”, “http://www.neu.edu.cn/default.htm”, nil, nil, SW_SHOWNORMAL); 2)如果將FileName引數設定為“mailto:”協議格式,那麼該函式將啟動預設郵件客戶程式,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若使用者機器中安裝了多個郵件客戶程式,則該函式將根據Windows 9x/NT登錄檔中mailto協議處理程式的設定確定啟動哪個郵件客戶程式。 格式一:mailto: 如:ShellExecute(handle, "open", "mailto:", nil, nil, SW_SHOWNORMAL);開啟新郵件視窗。 格式二:mailto:使用者賬號@郵件伺服器地址 如:ShellExecute(handle, "open", "mailto:[email protected]", nil, nil, SW_SHOWNORMAL); 開啟新郵件視窗,並自動填入收件人地址。若指定多個收件人地址,則收件人地址之間必須用分號或逗號分隔開(下同) 如:ShellExecute(this->m_hWnd, "open", "mailto:[email protected]", "", "", SW_SHOW); 格式三:mailto:使用者賬號@郵件伺服器地址?subject=郵件主題&body=郵件正文 如:ShellExecute(handle, "open", "mailto:[email protected]?subject=Hello&Body=This is a test", nil, nil, SW_SHOWNORMAL); 開啟新郵件視窗,並自動填入收件人地址、郵件主題和郵件正文。若郵件正文包括多行文字,則必須在每行文字之間加入換行轉義字元%0a。
例子(delphi): 在一個應用程式呼叫c:Project1.exe; ShellExecute(handle, ’open’,’c:Project1.exe’,’字串內容’,nil, SW_SHOWNORMAL); 在Project1.exe裡可以呼叫:
-
procedure TForm1.FormCreate(Sender: TObject);
-
var i:integer;
-
begin
-
for i:=1 to paramcount do
-
if ParamStr(i)〈〉’’ then showmessage(ParamStr(i));
-
end;
最後的那個引數,為視窗指定可視性方面的一個命令。 請用下述任何一個常數 SW_HIDE 隱藏視窗,活動狀態給令一個視窗 SW_MINIMIZE 最小化視窗,活動狀態給令一個視窗 SW_RESTORE 用原來的大小和位置顯示一個視窗,同時令其進入活動狀態 SW_SHOW 用當前的大小和位置顯示一個視窗,同時令其進入活動狀態 SW_SHOWMAXIMIZED 最大化視窗,並將其啟用 SW_SHOWMINIMIZED 最小化視窗,並將其啟用 SW_SHOWMINNOACTIVE 最小化一個視窗,同時不改變活動視窗 SW_SHOWNA 用當前的大小和位置顯示一個視窗,不改變活動視窗 SW_SHOWNOACTIVATE 用最近的大小和位置顯示一個視窗,同時不改變活動視窗
SW_SHOWNORMAL 與SW_RESTORE相同
3、深入淺出ShellExecute 譯者:徐景周(原作:Nishant S) Q: 如何開啟一個應用程式? 正如您所看到的,我並沒有傳遞程式的完整路徑。 ShellExecute(this->m_hWnd, "open", "calc.exe", "", "", SW_SHOW); 或ShellExecute(this->m_hWnd, "open", "notepad.exe", "c:\\MyLog.log", "", SW_SHOW); Q: 如何開啟一個同系統程式相關連的文件? ShellExecute(this->m_hWnd, "open", "c:\\abc.txt", "", "", SW_SHOW); Q: 如何開啟一個網頁? ShellExecute(this->m_hWnd, "open", "http://www.google.com", "", "", SW_SHOW); Q: 如何啟用相關程式,傳送EMAIL? ShellExecute(this->m_hWnd,"open", "mailto:[email protected]","","", SW_SHOW ); Q: 如何用系統印表機列印文件? ShellExecute(this->m_hWnd, "print", "c:\\abc.txt", "", "", SW_HIDE); Q: 如何用系統查詢功能來查詢指定檔案? ShellExecute(m_hWnd, "find", "d:\\nish", NULL, NULL, SW_SHOW); Q: 如何啟動一個程式,直到它執行結束?
SHELLEXECUTEINFO ShExecInfo = {0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; //當設定為"runas"時,表示以管理員許可權執行 ShExecInfo.lpFile = "c:\\MyProgram.exe"; ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
或:
PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; //This is an [in] parameter ZeroMemory(&StartupInfo, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); //Only compulsory field if(CreateProcess("c:\\winnt\\notepad.exe", NULL, NULL,NULL,FALSE,0,NULL, NULL,&StartupInfo,&ProcessInfo)) { WaitForSingleObject(ProcessInfo.hProcess,INFINITE); CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); } else { MessageBox("The process could not be started..."); }
Q: 如何顯示檔案或資料夾的屬性?
SHELLEXECUTEINFO ShExecInfo = {0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = "properties"; ShExecInfo.lpFile = "c:\\"; //can be a file as well ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo);
3.CreateProcess函式 可以設定繼承父程序許可權和控制代碼
函式原型:
BOOL CreateProcess
(
LPCTSTR lpApplicationName, [in]:
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes。
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
引數:
lpApplicationName:指向一個NULL結尾的、用來指定可執行模組的字串。
這個字串可以使可執行模組的絕對路徑,也可以是相對路徑,在後一種情況下,函式使用當前驅動器和目錄建立可執行模組的路徑。
這個引數可以被設為NULL,在這種情況下,可執行模組的名字必須處於 lpCommandLine 引數的最前面並由空格符與後面的字元分開。
這個被指定的模組可以是一個Win32應用程式。如果適當的子系統在當前計算機上可用的話,它也可以是其他型別的模組(如MS-DOS 或 OS/2)。
lpCommandLine:指向一個NULL結尾的、用來指定要執行的命令列。
這個引數可以為空,那麼函式將使用引數指定的字串當作要執行的程式的命令列。
如果lpApplicationName和lpCommandLine引數都不為空,那麼lpApplicationName引數指定將要被執行的模組,lpCommandLine引數指定將被執行的模組的命令列。新執行的程序可以使用GetCommandLine函式獲得整個命令列。C語言程式可以使用argc和argv引數。
如果lpApplicationName引數為空,那麼這個字串中的第一個被空格分隔的要素指定可執行模組名。如果檔名不包含副檔名,那麼.exe將被假定為預設的副檔名。如果檔名以一個點(.)結尾且沒有副檔名,或檔名中包含路徑,.exe將不會被加到後面。如果檔名中不包含路徑,Windows將按照如下順序尋找這個可執行檔案:
lpProcessAttributes:指向一個SECURITY_ATTRIBUTES結構體,這個結構體決定是否返回的控制代碼可以被子程序繼承。如果lpProcessAttributes引數為空(NULL),那麼控制代碼不能被繼承
lpThreadAttributes:指向一個SECURITY_ATTRIBUTES結構體,這個結構體決定是否返回的控制代碼可以被子程序繼承。如果lpThreadAttributes引數為空(NULL),那麼控制代碼不能被繼承
bInheritHandles:指示新程序是否從呼叫程序處繼承了控制代碼。如果引數的值為真,呼叫程序中的每一個可繼承的開啟控制代碼都將被子程序繼承。被繼承的控制代碼與原程序擁有完全相同的值和訪問許可權。
dwCreationFlags:指定附加的、用來控制優先類和程序的建立的標誌。以下的建立標誌可以以除下面列出的方式外的任何方式組合後指定。
值:CREATE_DEFAULT_ERROR_MODE
含義:新的程序不繼承呼叫程序的錯誤模式。CreateProcess函式賦予新程序當前的預設錯誤模式作為替代。應用程式可以呼叫SetErrorMode函式設定當前的預設錯誤模式。
這個標誌對於那些執行在沒有硬體錯誤環境下的多執行緒外殼程式是十分有用的。
對於CreateProcess函式,預設的行為是為新程序繼承呼叫者的錯誤模式。設定這個標誌以改變預設的處理方式。
值:CREATE_NEW_CONSOLE
含義:新的程序將使用一個新的控制檯,而不是繼承父程序的控制檯。這個標誌不能與DETACHED_PROCESS標誌一起使用。
值:CREATE_NEW_PROCESS_GROUP
含義:新程序將使一個程序樹的根程序。程序樹種的全部程序都是根程序的子程序。新程序樹的使用者識別符號與這個程序的識別符號是相同的,由lpProcessInformation引數返回。程序樹經常使用GenerateConsoleCtrlEvent函式允許傳送CTRL+C或CTRL+BREAK訊號到一組控制檯程序。
值:CREATE_SEPARATE_WOW_VDM
含義:(只適用於Windows NT)這個標誌只有當執行一個16位的Windows應用程式時才是有效的。如果被設定,新程序將會在一個私有的虛擬DOS機(VDM)中執行。另外,預設情況下所有的16位Windows應用程式都會在同一個共享的VDM中以執行緒的方式執行。單獨執行一個16位程式的優點是一個應用程式的崩潰只會結束這一個VDM的執行;其他那些在不同VDM中執行的程式會繼續正常的執行。同樣的,在不同VDM中執行的16位Windows應用程式擁有不同的輸入佇列,這意味著如果一個程式暫時失去響應,在獨立的VDM中的應用程式能夠繼續獲得輸入。
值:CREATE_SHARED_WOW_VDM
含義:(只適用於Windows NT)這個標誌只有當執行一個16位的Windows應用程式時才是有效的。如果WIN.INI中的Windows段的DefaultSeparateVDM選項被設定為真,這個標識使得CreateProcess函式越過這個選項並在共享的虛擬DOS機中執行新程序。
值:CREATE_SUSPENDED
含義:新程序的主執行緒會以暫停的狀態被建立,直到呼叫ResumeThread函式被呼叫時才執行。
值:CREATE_UNICODE_ENVIRONMENT
含義:如果被設定,由lpEnvironment引數指定的環境塊使用Unicode字元,如果為空,環境塊使用ANSI字元。
值:DEBUG_PROCESS
含義:如果這個標誌被設定,呼叫程序將被當作一個除錯程式,並且新程序會被當作被除錯的程序。系統把被除錯程式發生的所有除錯事件通知給偵錯程式。
如果你使用這個標誌建立程序,只有呼叫程序(呼叫CreateProcess函式的程序)可以呼叫WaitForDebugEvent函式。
值:DEBUG_ONLY_THIS_PROCESS
含義:如果此標誌沒有被設定且呼叫程序正在被除錯,新程序將成為除錯呼叫程序的偵錯程式的另一個除錯物件。如果呼叫程序沒有被除錯,有關除錯的行為就不會產生。
值:DETACHED_PROCESS
含義:對於控制檯程序,新程序沒有訪問父程序控制檯的許可權。新程序可以通過AllocConsole函式自己建立一個新的控制檯。這個標誌不可以與CREATE_NEW_CONSOLE標誌一起使用。
dwCreationFlags引數還用來控制新程序的優先類,優先類用來決定此程序的執行緒排程的優先順序。如果下面的優先順序類標誌都沒有被指定,那麼預設的優先類是NORMAL_PRIORITY_CLASS,除非被建立的程序是IDLE_PRIORITY_CLASS。在這種情況下子程序的預設優先類是IDLE_PRIORITY_CLASS。
可以下面的標誌中的一個:
優先順序:HIGH_PRIORITY_CLASS
含義:指示這個程序將執行時間臨界的任務,所以它必須被立即執行以保證正確。這個優先順序的程式優先於正常優先順序或空閒優先順序的程式。一個例子是Windows任務列表,為了保證當用戶呼叫時可以立刻響應,放棄了對系統負荷的考慮。確保在使用高優先順序時應該足夠謹慎,因為一個高優先順序的CPU關聯應用程式可以佔用幾乎全部的CPU可用時間。
優先順序:IDLE_PRIORITY_CLASS
含義:指示這個程序的執行緒只有在系統空閒時才會執行並且可以被任何高優先順序的任務打斷。例如螢幕保護程式。空閒優先順序會被子程序繼承。
優先順序:NORMAL_PRIORITY_CLASS
含義:指示這個程序沒有特殊的任務排程要求。
優先順序:REALTIME_PRIORITY_CLASS
含義:指示這個程序擁有可用的最高優先順序。一個擁有實時優先順序的程序的執行緒可以打斷所有其他程序執行緒的執行,包括正在執行重要任務的系統程序。例如,一個執行時間稍長一點的實時程序可能導致磁碟快取不足或滑鼠反映遲鈍。
lpEnvironment:指向一個新程序的環境塊。如果此引數為空,新程序使用呼叫程序的環境。
一個環境塊存在於一個由以NULL結尾的字串組成的塊中,這個塊也是以NULL結尾的。每個字串都是name=value的形式。
因為相等標誌被當作分隔符,所以它不能被環境變數當作變數名。
與其使用應用程式提供的環境塊,不如直接把這個引數設為空,系統驅動器上的當前目錄資訊不會被自動傳遞給新建立的程序。對於這個情況的探討和如何處理,請參見注釋一節。
環境塊可以包含Unicode或ANSI字元。如果lpEnvironment指向的環境塊包含Unicode字元,那麼dwCreationFlags欄位的CREATE_UNICODE_ENVIRONMENT標誌將被設定。如果塊包含ANSI字元,該標誌將被清空。
請注意一個ANSI環境塊是由兩個零位元組結束的:一個是字串的結尾,另一個用來結束這個快。一個Unicode環境塊石油四個零位元組結束的:兩個代表字串結束,另兩個用來結束塊。
lpCurrentDirectory:指向一個以NULL結尾的字串,這個字串用來指定子程序的工作路徑。這個字串必須是一個包含驅動器名的絕對路徑。如果這個引數為空,新程序將使用與呼叫程序相同的驅動器和目錄。這個選項是一個需要啟動啟動應用程式並指定它們的驅動器和工作目錄的外殼程式的主要條件。
lpStartupInfo:指向一個用於決定新程序的主窗體如何顯示的STARTUPINFO結構體。
lpProcessInformation:指向一個用來接收新程序的識別資訊的PROCESS_INFORMATION結構體。
返回值:
如果函式執行成功,返回非零值。
如果函式執行失敗,返回零,可以使用GetLastError函式獲得錯誤的附加資訊。
註釋:
CreateProcess函式用來執行一個新程式。WinExec和LoadModule函式依舊可用,但是它們同樣通過呼叫CreateProcess函式實現。
另外CreateProcess函式除了建立一個程序,還建立一個執行緒物件。這個執行緒將連同一個已初始化了的堆疊一起被建立,堆疊的大小由可執行檔案的檔案頭中的描述決定。執行緒由檔案頭處開始執行。
新程序和新執行緒的控制代碼被以全域性訪問許可權建立。對於這兩個控制代碼中的任一個,如果沒有安全描述符,那麼這個控制代碼就可以在任何需要控制代碼型別作為引數的函式中被使用。當提供安全描述符時,在接下來的時候當控制代碼被使用時,總是會先進行訪問許可權的檢查,如果訪問許可權檢查拒絕訪問,請求的程序將不能使用這個控制代碼訪問這個程序。
這個程序會被分配給一個32位的程序識別符號。直到程序中止這個識別符號都是有效的。它可以被用來標識這個程序,或在OpenProcess函式中被指定以開啟這個程序的控制代碼。程序中被初始化了的執行緒一樣會被分配一個32位的執行緒識別符號。這個識別符號直到縣城中止都是有效的且可以用來在系統中唯一標識這個執行緒。這些識別符號在PROCESS_INFORMATION結構體中返回。
當在lpApplicationName或lpCommandLine引數中指定應用程式名時,應用程式名中是否包含副檔名都不會影響執行,只有一種情況例外:一個以.com為副檔名的MS-DOS程式或Windows程式必須包含.com副檔名。
呼叫程序可以通過WaitForInputIdle函式來等待新程序完成它的初始化並等待使用者輸入。這對於父程序和子程序之間的同步是極其有用的,因為CreateProcess函式不會等待新程序完成它的初始化工作。舉例來說,在試圖與新程序關聯的視窗之前,程序應該先呼叫WaitForInputIdle。
首選的結束一個程序的方式是呼叫ExitProcess函式,因為這個函式通知這個程序的所有動態連結庫(DLLs)程式已進入結束狀態。其他的結束程序的方法不會通知關聯的動態連結庫。注意當一個程序呼叫ExitProcess時,這個程序的其他縣城沒有機會執行其他任何程式碼(包括關聯動態連結庫的終止程式碼)。
ExitProcess, ExitThread, CreateThread, CreateRemoteThread,當一個程序啟動時(呼叫了CreateProcess的結果)是在程序中序列化進行的。在一段地址空間中,同一時間內這些事件中只有一個可以發生。這意味著下面的限制將保留:
*在程序啟動和DLL初始化階段,新的執行緒可以被建立,但是直到程序的DLL初始化完成前它們都不能開始執行。
*在DLL初始化或卸下例程中程序中只能有一個執行緒。
*直到所有的執行緒都完成DLL初始化或卸下後,ExitProcess函式才返回。
在程序中的所有執行緒都終止且程序所有的控制代碼和它們的執行緒被通過呼叫CloseHandle函式終止前,程序會留在系統中。程序和主執行緒的控制代碼都必須通過呼叫CloseHandle函式關閉。如果不再需要這些控制代碼,最好在建立程序後立刻關閉它們。
當程序中最後一個執行緒終止時,下列的事件發生:
*所有由程序開啟的物件都會關閉。
*程序的終止狀態(由GetExitCodeProcess函式返回)從它的初始值STILL_ACTIVE變為最後一個結束的執行緒的結束狀態。
*主執行緒的執行緒物件被設定為標誌狀態,供其他等待這個物件的執行緒使用。
*程序物件被設定為標誌狀態,供其他等待這個物件的執行緒使用。
假設當前在C盤上的目錄是\MSVC\MFC且有一個環境變數叫做C:,它的值是C:\MSVC\MFC,就像前面lpEnvironment中提到過的那樣,這樣的系統驅動器上的目錄資訊在CreateProcess函式的lpEnvironment引數不為空時不會被自動傳遞到新程序裡。一個應用程式必須手動地把當前目錄資訊傳遞到新的程序中。為了這樣做,應用程式必須直接建立環境字串,並把它們按字母順序排列(因為Windows NT和Windows 95使用一種簡略的環境變數),並把它們放進lpEnvironment中指定的環境塊中。類似的,他們要找到環境塊的開頭,又要重複一次前面提到的環境塊的排序。
一種獲得驅動器X的當前目錄變數的方法是呼叫GetFullPathName("x:",..)。這避免了一個應用程式必須去掃描環境塊。如果返回的絕對路徑是X:\,就不需要把這個值當作一個環境資料去傳遞了,因為根目錄是驅動器X上的新程序的預設當前目錄。
由CreateProcess函式返回的控制代碼對於程序物件具有PROCESS_ALL_ACCESS的訪問許可權。
由lpcurrentDirectory引數指定的當前目錄室子程序物件的當前目錄。lpCommandLine引數指定的第二個專案是父程序的當前目錄。
對於Windows NT,當一個程序在指定了CREATE_NEW_PROCESS_GROUP的情況下被建立時,一個對於SetConsoleCtrlHandler(NULL,True)的呼叫被用在新的程序上,這意味著對新程序來說CTRL+C是無效的。這使得上層的外科程式可以自己處理CTRL+C資訊並有選擇的把這些訊號傳遞給子程序。CTRL+BREAK依舊有效,並可被用來中斷程序/程序樹的執行。
安全註釋:
第一個引數lpApplicationName可能是空,這種情況下,可執行檔案的名字必須在lpCommandLine中,lpCommandLine引數中可以包含空格。如果可執行檔案或路徑中包含空格,那麼就會有執行不正確檔案的風險,這是由於這個函式解析空格的方法引起的。例如:下邊這個例子就很危險,因為它試圖執行Program.exe檔案,如果這個檔案存在,它就會代替MyApp.exe檔案的執行。
CreateProcess(NULL,”C:\\Program Files\\MyApp.exe”,…….)
如果有惡意的使用者在系統編寫了一個名為Program.exe的檔案,那麼任何呼叫CreateProcess函式,且在檔案路徑中使用Program Files資料夾的引數,都有可能會執行Program.exe檔案,而不是執行本來打算執行的檔案。
要避免這個問題,可以不要將NULL值傳遞給lpApplicationName引數,或者在lpCommandLine中使用雙引號(轉義符)括起可執行檔案的全路徑名,如下所示:
CreateProcess(NULL,”\”C:\\Program Files\\MyApp.exe\” -L -S”,…….)
-L和-S是MyApp.exe可執行檔案的引數。
最後要說明的一點是:在lpApplicationName中的引數和lpCommandLine中的第一個引數是一樣的,有人說顯得有些重複,其實這樣做純粹是一種被公認化了習慣!
此外還有CreateProcessAsUser函式