CreateProcessW 函式 (processthreadsapi.h)
建立新的進程及其主要線程。 新的進程會在呼叫進程的安全性內容中執行。
如果呼叫進程模擬另一位使用者,新進程會使用令牌進行呼叫進程,而不是模擬令牌。 若要在模擬令牌所代表使用者的安全性內容中執行新進程,請使用 CreateProcessAsUser 或 CreateProcessWithLogonW 函式。
語法
BOOL CreateProcessW(
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
參數
[in, optional] lpApplicationName
要執行的模組名稱。 此課程模組可以是以 Windows 為基礎的應用程式。 如果本機計算機上有適當的子系統可用,它可以是一些其他類型的模組(例如,MS-DOS 或 OS/2)。
字串可以指定要執行之模組的完整路徑和檔名,也可以指定部分名稱。 在部分名稱的情況下,函式會使用目前的磁碟驅動器和目前目錄來完成規格。 函式不會使用搜尋路徑。 此參數必須包含擴展名;未假設預設延伸模組。
lpApplicationName 參數可以 NULL。 在此情況下,模組名稱必須是 lpCommandLine 字串中的第一個空格符分隔標記。 如果您使用包含空格的長檔名,請使用引號字串來指出檔名的結尾和自變數的開頭;否則,檔名模棱兩可。 例如,請考慮字串 「c:\program files\sub dir\program name」。。 此字串可以透過數種方式來解譯。 系統會嘗試以下列順序解譯可能性:
- c:\program.exe
- c:\program files\sub.exe
- c:\program files\sub dir\program.exe
- c:\program files\sub dir\program name.exe
如果可執行模組是16位應用程式,lpApplicationName 應 NULL,而 lpCommandLine 所指向的字元串應該指定可執行模組及其自變數。
若要執行批次處理檔,您必須啟動命令解釋器;將 lpApplicationName 設定為 cmd.exe,並將 lpCommandLine 設為下列自變數:/c 加上批處理文件的名稱。
[in, out, optional] lpCommandLine
要執行的命令行。
此字串的最大長度為 32,767 個字元,包括 Unicode 終止 Null 字元。 如果 lpApplicationNameNULL,則 lpCommandLine 的模組名稱部分限制為 MAX_PATH 個字元。
此函式的 Unicode 版本 CreateProcessW可以修改此字串的內容。 因此,此參數不能是唯讀記憶體的指標(例如 const 變數或常值字串)。 如果此參數是常數位符串,函式可能會造成存取違規。
lpCommandLine 參數可以是 NULL。 在此情況下,函式會使用 lpApplicationName 所指向的字串作為命令行。
如果 lpApplicationName 和 lpCommandLine 都是非NULL,則 lpApplicationName 所指向的 null 終止字符串 會指定要執行的模組,而 lpCommandLine 所 指向的 null 終止字符串 會指定命令行。 新的程式可以使用 GetCommandLine 來擷取整個命令行。 以 C 撰寫的主控台進程可以使用 argc 和 argv 自變數來剖析命令行。 因為 argv[0] 是模組名稱,C 程式設計人員通常會重複模組名稱作為命令行中的第一個令牌。
如果 lpApplicationName 為 NULL,命令行的第一個空格符分隔標記會指定模組名稱。 如果您使用包含空格的長檔名,請使用引號字串來指出檔名的結尾和自變數的開頭(請參閱 lpApplicationName 參數的說明)。 如果檔名不包含擴展名,則會附加 .exe。 因此,如果擴展名是.com,此參數必須包含.com擴展名。 如果檔名以沒有擴展名的句號 (.) 結尾,或檔名包含路徑,則不會附加 .exe。 如果檔案名不包含目錄路徑,系統會依下列順序搜尋可執行檔:
- 應用程式從中載入的目錄。
- 父進程的目前目錄。
- 32 位 Windows 系統目錄。 使用 GetSystemDirectory 函式來取得此目錄的路徑。
- 16 位 Windows 系統目錄。 沒有可取得此目錄路徑的函式,但會加以搜尋。 此目錄的名稱為 System。
- Windows 目錄。 使用 GetWindowsDirectory 函式來取得此目錄的路徑。
- PATH 環境變數中所列的目錄。 請注意,此函式不會搜尋 應用程式路徑 登錄機碼所指定的個別應用程式路徑。 若要在搜尋順序中包含此個別應用程式路徑,請使用 ShellExecute 函式。
[in, optional] lpProcessAttributes
SECURITY_ATTRIBUTES 結構的指標,決定子進程是否可以繼承傳回給新進程物件的句柄。 如果 lpProcessAttributesNULL,則無法繼承句柄。
lpSecurityDescriptor 結構的成員會指定新進程的安全性描述元。 如果 lpProcessAttributes 為 NULL 或 lpSecurityDescriptorNULL,則進程會取得預設的安全性描述元。 進程的預設安全性描述元中的 ACL 來自建立者的主要令牌。Windows XP:進程的預設安全性描述元中的 ACL 來自建立者的主要或模擬令牌。 使用SP2和 Windows Server 2003 的 Windows XP 變更此行為。
[in, optional] lpThreadAttributes
SECURITY_ATTRIBUTES 結構的指標,決定子進程是否可以繼承傳回給新線程物件的句柄。 如果 lpThreadAttributes 為 NULL,則無法繼承句柄。
lpSecurityDescriptor 結構的成員會指定主線程的安全性描述元。 如果 lpThreadAttributes 為 NULL 或 lpSecurityDescriptor 為 NULL,線程會取得預設的安全性描述元。 線程的預設安全性描述元中的 ACL 來自進程令牌。Windows XP:線程的預設安全性描述元中的 ACL 來自建立者的主要或模擬令牌。 使用SP2和 Windows Server 2003 的 Windows XP 變更此行為。
[in] bInheritHandles
如果此參數為TRUE,則呼叫進程中的每個可繼承句柄都會由新進程繼承。 如果參數為 FALSE,則不會繼承句柄。 請注意,繼承的句柄與原始句柄具有相同的值和訪問許可權。 如需可繼承句柄的其他討論,請參閱。
終端機服務:您無法跨會話繼承句柄。 此外,如果此參數為TRUE,您必須在與呼叫端相同的會話中建立進程。
受保護的進程光 (PPL) 進程:PPL 進程建立非 PPL 進程時會封鎖泛型句柄繼承,因為不允許從非 PPL 進程到 PPL 進程PROCESS_DUP_HANDLE。 請參閱 處理安全性和訪問許可權
[in] dwCreationFlags
控制優先順序類別和建立進程的旗標。 如需值清單,請參閱 進程建立旗標。
此參數也會控制新進程的優先順序類別,用來判斷進程線程的排程優先順序。 如需值清單,請參閱 GetPriorityClass。 如果未指定任何優先順序類別旗標,除非建立程式的優先順序類別 IDLE_PRIORITY_CLASS 或 BELOW_NORMAL_PRIORITY_CLASS,否則優先順序類別預設為 NORMAL_PRIORITY_CLASS。 在此情況下,子進程會收到呼叫進程的預設優先權類別。
如果 dwCreationFlags 參數的值為 0:
- 進程會同時繼承呼叫端和父代控制台的錯誤模式。
- 假設新進程的環境區塊包含 ANSI 字元(如需詳細資訊,請參閱 lpEnvironment 參數)。
- 16 位 Windows 應用程式會在共用的虛擬 DOS 機器 (VDM) 中執行。
[in, optional] lpEnvironment
新進程的環境區塊指標。 如果此參數 NULL,則新進程會使用呼叫進程的環境。
環境區塊是由 Null 終止字串的 Null 終止區塊所組成。 每個字串的格式如下:
名稱=值\0
因為等號會當做分隔符使用,所以不能用在環境變數的名稱中。
環境區塊可以包含 Unicode 或 ANSI 字元。 如果 lpEnvironment 所指向的環境區塊包含 Unicode 字元,請確定 dwCreationFlags 包含 CREATE_UNICODE_ENVIRONMENT。
如果進程的環境區塊總大小超過 32,767 個字元,則此函式的 ANSI 版本 CreateProcessA 失敗。
請注意,ANSI 環境區塊會以兩個零位元節終止:一個用於最後一個字串,另一個用來終止區塊。 Unicode 環境區塊會以四個零位元節終止:兩個用於最後一個字元串,另外兩個則終止區塊。
[in, optional] lpCurrentDirectory
進程目前目錄的完整路徑。 字串也可以指定 UNC 路徑。
如果此參數 NULL,新進程將會有與呼叫進程相同的目前磁碟驅動器和目錄。 (此功能主要針對需要啟動應用程式的殼層,並指定其初始磁碟驅動器和工作目錄。
[in] lpStartupInfo
STARTUPINFO 或 STARTUPINFOEX 結構的指標。
若要設定擴充屬性,請使用 STARTUPINFOEX 結構,並在 dwCreationFlags 參數中指定EXTENDED_STARTUPINFO_PRESENT。
STARTUPINFO 或 STARTUPINFOEX 中的句柄,必須在不再需要時關閉 CloseHandle。
[out] lpProcessInformation
PROCESS_INFORMATION 結構的指標,可接收新進程的識別資訊。
PROCESS_INFORMATION 中的句柄必須在不再需要時關閉 CloseHandle。
傳回值
如果函式成功,則傳回值為非零值。
如果函式失敗,傳回值為零。 若要取得擴充的錯誤資訊,請呼叫 GetLastError。
請注意,函式會在進程完成初始化之前傳回。 如果找不到必要的 DLL 或無法初始化,進程就會終止。 若要取得行程的終止狀態,請呼叫 getExitCodeProcess 。
言論
進程會指派進程標識碼。 標識元有效,直到進程終止為止。 它可用來識別進程,或在 OpenProcess 函式中指定,以開啟進程的句柄。 進程中的初始線程也會指派線程標識碼。 您可以在 OpenThread 函式中指定它,以開啟線程的句柄。 標識元在線程終止之前有效,而且可用來唯一識別系統中的線程。 這些標識碼會在 PROCESS_INFORMATION 結構中傳回。
操作系統提供給進程的命令行可執行檔名稱不一定與呼叫進程提供給 createProcess 函式
呼叫線程可以使用 WaitForInputIdle 函式等候,直到新進程完成初始化,並正在等候使用者輸入,而沒有任何輸入擱置。 這對於父進程和子進程之間的同步處理很有用,因為 CreateProcess 傳回,而不需要等待新進程完成初始化。 例如,建立程式會先使用 waitForInputIdle,再嘗試尋找與新進程相關聯的視窗。
關閉進程的慣用方式是使用 ExitProcess 函式,因為此函式會將接近終止的通知傳送給附加至進程的所有 DLL。 關閉進程的其他方式不會通知附加 DLL。 請注意,當線程呼叫 ExitProcess時,進程的其他線程會終止,而沒有機會執行任何其他程式碼(包括附加 DLL 的線程終止程式代碼)。 如需詳細資訊,請參閱 終止進程。
父進程可以在程式建立期間直接改變子進程的環境變數。 這是進程直接變更另一個進程的環境設定時,唯一的情況。 如需詳細資訊,請參閱 變更環境變數。
如果應用程式提供環境區塊,系統磁碟驅動器的目前目錄資訊不會自動傳播到新的進程。 例如,有一個名為 =C 的環境變數:其值是磁碟驅動器 C 上的目前目錄。應用程式必須手動將當前目錄資訊傳遞至新的進程。 若要這樣做,應用程式必須明確地建立這些環境變數字串、依字母順序排序它們(因為系統使用已排序的環境),並將其放入環境區塊中。 一般而言,由於環境區塊排序順序,它們會位於環境區塊的前面。
取得磁碟驅動器 X 目前目錄資訊的其中一種方法是進行下列呼叫:GetFullPathName("X:", ...)
。 這可避免應用程式必須掃描環境區塊。 如果傳回的完整路徑是 X:,就不需要將該值當做環境數據傳遞,因為根目錄是新進程之磁碟驅動器 X 的預設目前目錄。
使用指定的 CREATE_NEW_PROCESS_GROUP 建立進程時,會代表新進程進行隱含呼叫 SetConsoleCtrlHandler(NULL,TRUE) ;這表示新進程已停用 CTRL+C。 這可讓殼層自行處理 CTRL+C,並選擇性地將該訊號傳遞給子進程。 CTRL+BREAK 未停用,而且可用來中斷進程/進程群組。
根據預設,傳遞
安全性備註
第一個參數 lpApplicationName,可以 NULL,在此情況下,可執行檔名稱必須位於 lpCommandLine所指向的空格符分隔字串中。 如果可執行檔或路徑名稱中有空格,則因為函式剖析空格的方式,可能會執行不同的可執行檔。 下列範例很危險,因為函式會嘗試執行 「Program.exe」,如果存在,而不是 「MyApp.exe」。 LPTSTR szCmdline = _tcsdup(TEXT("C:\\Program Files\\MyApp -L -S"));
CreateProcess(NULL, szCmdline, /* ... */);
如果惡意使用者是在系統上建立名為 「Program.exe」 的應用程式,則使用 Program Files 目錄不正確地呼叫 CreateProcess 的任何程式都會執行此應用程式,而不是預期的應用程式。
若要避免此問題,請勿針對 lpApplicationName傳遞 NULL。 如果您針對 lpApplicationName傳遞 NULL,請使用 lpCommandLine中可執行文件路徑的引號,如下列範例所示。
LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));
CreateProcess(NULL, szCmdline, /*...*/);
例子
如需範例,請參閱 建立進程。
注意
processthreadsapi.h 標頭會將 CreateProcess 定義為別名,根據 UNICODE 預處理器常數的定義,自動選取此函式的 ANSI 或 Unicode 版本。 混合使用編碼中性別名與非編碼中性的程序代碼,可能會導致編譯或運行時間錯誤不符。 如需詳細資訊,請參閱函式原型的
要求
要求 | 價值 |
---|---|
最低支援的用戶端 | Windows XP [傳統型應用程式 |UWP 應用程式] |
支援的最低伺服器 | Windows Server 2003 [傳統型應用程式 |UWP 應用程式] |
目標平臺 | 窗戶 |
標頭 | processthreadsapi.h (包括 Windows Server 2003 上的 Windows.h、Windows Vista、Windows 7、Windows Server 2008 Windows Server 2008 R2) |
連結庫 | Kernel32.lib |
DLL | Kernel32.dll |