CreateProcessA 函式 (processthreadsapi.h)
建立新的進程及其主要執行緒。 新的進程會在呼叫進程的安全性內容中執行。
如果呼叫進程模擬另一個使用者,新進程會使用權杖進行呼叫進程,而不是模擬權杖。 若要在模擬權杖所代表使用者的安全性內容中執行新進程,請使用 CreateProcessAsUser 或 CreateProcessWithLogonW 函式。
語法
BOOL CreateProcessA(
[in, optional] LPCSTR lpApplicationName,
[in, out, optional] LPSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCSTR lpCurrentDirectory,
[in] LPSTARTUPINFOA 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 字元。 如果 lpApplicationName 為 Null, 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結構的指標,決定子進程是否可以繼承新進程物件的傳回控制碼。 如果 lpProcessAttributes 為 Null,則無法繼承控制碼。
結構的 lpSecurityDescriptor 成員會指定新進程的安全性描述元。 如果 lpProcessAttributes 為 Null 或 lpSecurityDescriptor 為 Null,則進程會取得預設的安全性描述元。 進程的預設安全性描述元中的 ACL 來自建立者的主要權杖。Windowsxp: 進程的預設安全性描述元中的 ACL 來自建立者的主要或模擬權杖。 此行為隨著 WINDOWS XP SP2 和 Windows Server 2003 而變更。
[in, optional] lpThreadAttributes
SECURITY_ATTRIBUTES結構的指標,決定子進程是否可以繼承新執行緒物件的傳回控制碼。 如果 lpThreadAttributes 為 Null,則無法繼承控制碼。
結構的 lpSecurityDescriptor 成員會指定主執行緒的安全性描述元。 如果 lpThreadAttributes 為 Null 或 lpSecurityDescriptor 為 Null,則執行緒會取得預設的安全性描述元。 執行緒預設安全性描述元中的 ACL 來自進程權杖。Windowsxp: 執行緒預設安全性描述元中的 ACL 來自建立者的主要或模擬權杖。 此行為隨著 WINDOWS XP SP2 和 Windows Server 2003 而變更。
[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 應用程式會在共用的 Virtual DOS 電腦中執行, (VDM) 。
[in, optional] lpEnvironment
新進程的環境區塊指標。 如果此參數為 Null,新進程會使用呼叫進程的環境。
環境區塊是由 Null 終止字串的 Null 終止區塊所組成。 每個字串的格式如下:
名字=value\0
因為等號是當做分隔符號使用,所以不能用在環境變數的名稱中。
環境區塊可以包含 Unicode 或 ANSI 字元。 如果 lpEnvironment 所指向的環境區塊包含 Unicode 字元,請確定 dwCreationFlags 包含 CREATE_UNICODE_ENVIRONMENT。
如果進程的環境區塊總大小超過 32,767 個字元, 則 CreateProcessA 會失敗此函式的 ANSI 版本。
請注意,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 未停用,而且可用來中斷進程/進程群組。
根據預設,傳遞 TRUE 作為 bInheritHandles 參數的值會導致新進程繼承所有可繼承的控制碼。 對於同時從多個執行緒建立進程的應用程式,這可能會造成問題,但希望每個進程都繼承不同的控制碼。 應用程式可以使用 UpdateProcThreadAttributeList 函式搭配 PROC_THREAD_ATTRIBUTE_HANDLE_LIST 參數,以提供特定進程要繼承的控制碼清單。
安全性備註
第一個參數 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 應用程式] |
目標平台 | Windows |
標頭 | processthreadsapi.h (Windows Server 2003、Windows Vista、Windows 7、Windows Server 2008 Windows Server 2008 R2) |
程式庫 | Kernel32.lib |
DLL | Kernel32.dll |
另請參閱
意見反應
提交並檢視相關的意見反應