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 文字も含まれます。 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 は、作成者のプライマリ トークンから取得されます。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 プロセスへのPROCESS_DUP_HANDLEが許可されていないため、PPL プロセスが非 PPL プロセスを作成すると、汎用ハンドルの継承がブロックされます。 「プロセスのセキュリティとアクセス権」を参照してください
[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が含まれていることを確認してください。
この関数の ANSI バージョンでは、プロセスの環境ブロックの合計サイズが 32,767 文字を超えると 、CreateProcessA は失敗します。
ANSI 環境ブロックは 2 つのゼロ バイトで終了されます。最後の文字列の場合は 1 つ、ブロックを終了する場合はもう 1 つです。 Unicode 環境ブロックは 4 つのゼロ バイトで終了されます。最後の文字列の場合は 2 バイト、ブロックを終了するにはさらに 2 バイトです。
[in, optional] lpCurrentDirectory
プロセスの現在のディレクトリへの完全なパス。 文字列では UNC パスを指定することもできます。
このパラメーターが NULL の場合、新しいプロセスの現在のドライブとディレクトリは呼び出し元のプロセスと同じになります。 (この機能は、主にアプリケーションを起動し、初期ドライブと作業ディレクトリを指定する必要があるシェル用に提供されます。
[in] lpStartupInfo
STARTUPINFO または STARTUPINFOEX 構造体へのポインター。
拡張属性を設定するには、 STARTUPINFOEX 構造体を使用し、 dwCreationFlags パラメーターにEXTENDED_STARTUPINFO_PRESENTを指定します。
STARTUPINFO または STARTUPINFOEX のハンドルは、必要なくなったときに CloseHandle で閉じる必要があります。
[out] lpProcessInformation
新しいプロセスに関する識別情報を受け取る PROCESS_INFORMATION 構造体へのポインター。
PROCESS_INFORMATIONのハンドルは、必要なくなったときに CloseHandle で閉じる必要があります。
戻り値
関数が成功すると、戻り値は 0 以外になります。
関数が失敗した場合は、0 を返します。 詳細なエラー情報を得るには、GetLastError を呼び出します。
この関数は、プロセスの初期化が完了する前に が返されることに注意してください。 必要な DLL が見つからないか、初期化に失敗した場合、プロセスは終了します。 プロセスの終了状態を取得するには、 GetExitCodeProcess を呼び出します。
注釈
プロセスにはプロセス識別子が割り当てられます。 識別子は、プロセスが終了するまで有効です。 プロセスを識別するために使用するか、 OpenProcess 関数で指定してプロセスへのハンドルを開くことができます。 プロセス内の初期スレッドにもスレッド識別子が割り当てられます。 OpenThread 関数で指定して、スレッドへのハンドルを開くことができます。 識別子は、スレッドが終了するまで有効であり、システム内のスレッドを一意に識別するために使用できます。 これらの識別子は、 PROCESS_INFORMATION 構造体で返されます。
オペレーティング システムがプロセスに提供するコマンド ラインの実行可能ファイルの名前は、呼び出し元のプロセスが CreateProcess 関数に与えるコマンド ラインの名前と必ずしも同じではありません。 オペレーティング システムは、完全修飾パスなしで提供される実行可能名の前に完全修飾パスを付加できます。
呼び出し元のスレッドは WaitForInputIdle 関数を使用して、新しいプロセスが初期化を完了し、入力が保留中でないユーザー入力を待機するまで待機できます。 これは、親プロセスと子プロセスの間の同期に役立ちます。 CreateProcess は 、新しいプロセスが初期化を完了するのを待たずに を返します。 たとえば、作成プロセスでは、新しいプロセスに関連付けられているウィンドウを検索する前に WaitForInputIdle を使用します。
プロセスをシャットダウンする推奨される方法は 、ExitProcess 関数を使用することです。この関数は、プロセスにアタッチされているすべての DLL に終了に近づくという通知を送信するためです。 プロセスをシャットダウンするその他の方法では、アタッチされている DLL には通知されません。 スレッドが ExitProcess を呼び出すと、プロセスの他のスレッドは、追加のコード (アタッチされた DLL のスレッド終了コードを含む) を実行する機会なしに終了されることに注意してください。 詳細については、「 プロセスの終了」を参照してください。
親プロセスは、プロセスの作成時に子プロセスの環境変数を直接変更できます。 これは、プロセスが別のプロセスの環境設定を直接変更できる唯一の状況です。 詳細については、「環境変数の 変更」を参照してください。
アプリケーションが環境ブロックを提供する場合、システム ドライブの現在のディレクトリ情報は、新しいプロセスに自動的に反映されません。 たとえば、=C: という名前の環境変数があり、その値はドライブ C の現在のディレクトリです。アプリケーションは、現在のディレクトリ情報を新しいプロセスに手動で渡す必要があります。 これを行うには、アプリケーションでこれらの環境変数文字列を明示的に作成し、アルファベット順に並べ替えて (システムが並べ替えられた環境を使用するため)、それらを環境ブロックに配置する必要があります。 通常、環境ブロックの並べ替え順序により、環境ブロックの前面に移動します。
ドライブ X の現在のディレクトリ情報を取得する方法の 1 つは、 を呼び出す GetFullPathName("X:", ...)
方法です。 そのため、アプリケーションで環境ブロックをスキャンする必要がなくなります。 返される完全なパスが X: の場合、ルート ディレクトリは新しいプロセスのドライブ X の既定の現在のディレクトリであるため、その値を環境データとして渡す必要はありません。
CREATE_NEW_PROCESS_GROUPを指定してプロセスを作成すると、新しいプロセスに代わって SetConsoleCtrlHandler(NULL,TRUE) の暗黙的な呼び出しが行われます。これは、新しいプロセスで Ctrl + C が無効になっていることを意味します。 これにより、シェルは Ctrl + C 自体を処理し、そのシグナルをサブプロセスに選択的に渡すことができます。 Ctrl + BREAK は無効ではなく、プロセス/プロセス グループを中断するために使用できます。
既定では、bInheritHandles パラメーターの値として TRUE を渡すと、すべての継承可能なハンドルが新しいプロセスによって継承されます。 これは、複数のスレッドから同時にプロセスを作成するが、各プロセスが異なるハンドルを継承することを望んでいるアプリケーションでは問題になる可能性があります。 アプリケーションでは、 UpdateProcThreadAttributeList 関数を PROC_THREAD_ATTRIBUTE_HANDLE_LIST パラメーターと共に使用して、特定のプロセスによって継承されるハンドルの一覧を提供できます。
セキュリティに関する備考
最初のパラメーター lpApplicationName には NULL を指定できます。この場合、実行可能ファイル名は lpCommandLine が指す空白で区切られた文字列に含まれている必要があります。 実行可能ファイルまたはパス名にスペースが含まれている場合、関数がスペースを解析する方法により、別の実行可能ファイルが実行される可能性があります。 次の例は、関数が "MyApp.exe" ではなく"Program.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 バージョンを自動的に選択します。 encoding-neutral エイリアスの使用を encoding-neutral ではないコードと混在すると、コンパイル エラーまたはランタイム エラーが発生する不一致が発生する可能性があります。 詳細については、「 関数プロトタイプの規則」を参照してください。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows XP [デスクトップ アプリ | UWP アプリ] |
サポートされている最小のサーバー | Windows Server 2003 [デスクトップ アプリのみ | UWP アプリ] |
対象プラットフォーム | Windows |
ヘッダー | processthreadsapi.h (Windows Server 2003、Windows Vista、Windows 7、Windows Server 2008 Windows Server 2008 R2 の Windows.h を含む) |
Library | Kernel32.lib |
[DLL] | Kernel32.dll |