CreateProcessA 函式 (processthreadsapi.h)

建立新的進程及其主要線程。 新的進程會在呼叫進程的安全性內容中執行。

如果呼叫進程模擬另一個使用者,新進程會使用令牌進行呼叫進程,而不是模擬令牌。 若要在模擬令牌所代表使用者的安全性內容中執行新進程,請使用 CreateProcessAsUserCreateProcessWithLogonW 函式。

語法

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」。。 此字串可以透過數種方式解譯。 系統會嘗試以下列順序解譯可能性:

  1. c:\program.exe
  2. c:\program files\sub.exe
  3. c:\program files\sub dir\program.exe
  4. 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 所指向的字串作為命令行。

如果 lpApplicationNamelpCommandLine 都是非 NULL,則 lpApplicationName 所指向的 Null 終止字串會指定要執行的模組,而 lpCommandLine 所指向的 Null 終止字串會指定命令行。 新的程式可以使用 GetCommandLine 來擷取整個命令行。 以 C 撰寫的控制台程式可以使用 argcargv 自變數來剖析命令行。 因為 argv[0] 是模組名稱,C 程式設計人員通常會在命令行中重複模組名稱作為第一個令牌。

如果 lpApplicationName 為 NULL,命令行的第一個空格符分隔標記會指定模組名稱。 如果您使用包含空格的長檔名,請使用引號字串來指出檔名結尾的位置,而自變數會開始 (請參閱 lpApplicationName 參數的說明) 。 如果檔名不包含擴展名,則會附加 .exe。 因此,如果擴展名.com,此參數必須包含.com擴展名。 如果檔名以不含擴展名的句號結尾 (.) ,或檔名包含路徑,則不會附加 .exe。 如果檔案名不包含目錄路徑,系統會以下列順序搜尋可執行檔:

  1. 應用程式從中載入的目錄。
  2. 父進程的目前目錄。
  3. 32 位 Windows 系統目錄。 使用 GetSystemDirectory 函式 來取得此目錄的路徑。
  4. 16 位 Windows 系統目錄。 沒有函式可取得此目錄的路徑,但已搜尋。 此目錄的名稱為 System。
  5. Windows 目錄。 使用 GetWindowsDirectory 函式 來取得此目錄的路徑。
  6. PATH 環境變數中列出的目錄。 請注意,此函式不會搜尋 應用程式路徑 登錄機碼所指定的個別應用程式路徑。 若要在搜尋順序中包含此個別應用程式路徑,請使用 ShellExecute 函式。
系統會將終止 Null 字元新增至命令行字串,以分隔檔名與自變數。 這會將原始字串分割成兩個字串以供內部處理。

[in, optional] lpProcessAttributes

SECURITY_ATTRIBUTES 結構的指標,決定子進程是否可以繼承新進程對象的傳回句柄。 如果 lpProcessAttributesNULL,則無法繼承句柄。

結構的 lpSecurityDescriptor 成員會指定新進程的安全性描述元。 如果 lpProcessAttributes 為 NULL 或 lpSecurityDescriptorNULL,則進程會取得預設的安全性描述元。 進程的預設安全性描述元中的 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。 請參閱 處理安全性和訪問許可權

Windows 7: 即使參數為 FALSE,仍會繼承STD_INPUT_HANDLE、STD_OUTPUT_HANDLE和STD_ERROR_HANDLE。

[in] dwCreationFlags

控制優先順序類別和建立進程的旗標。 如需值清單,請參閱 進程建立旗標

此參數也會控制新進程的優先順序類別,用來判斷進程線程的排程優先順序。 如需值清單,請參閱 GetPriorityClass。 如果未指定任何優先順序類別旗標,則除非建立程式的優先順序類別是IDLE_PRIORITY_CLASSBELOW_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

STARTUPINFOSTARTUPINFOEX 結構的指標。

若要設定擴充屬性,請使用 STARTUPINFOEX 結構,並在 dwCreationFlags 參數中指定EXTENDED_STARTUPINFO_PRESENT。

在 STARTUPINFOSTARTUPINFOEX 中的句柄不再需要時,必須使用 CloseHandle 關閉。

重要 呼叫端負責確保 STARTUPINFO 中的標準句柄字段包含有效的句柄值。 即使 dwFlags 成員指定 STARTF_USESTDHANDLES,這些字段也不會複製到子進程而不驗證。 不正確的值可能會導致子進程錯誤或當機。 使用 應用程式驗證器 運行時間驗證工具來偵測無效的句柄。
 

[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 的任何程式都會執行此應用程式,而不是預期的應用程式。

若要避免這個問題,請勿傳遞 lpApplicationNameNULL。 如果您為 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

另請參閱

CloseHandle

ShellExecuteA

CreateProcessAsUser

CreateProcessWithLogonW

ExitProcess

GetCommandLine

GetEnvironmentStrings

GetExitCodeProcess

GetFullPathName

GetStartupInfo

OpenProcess

PROCESS_INFORMATION

處理序和執行緒函式

程序

SECURITY_ATTRIBUTES

STARTUPINFO

STARTUPINFOEX

SetErrorMode

TerminateProcess

WaitForInputIdle