CreateProcessA-Funktion (processthreadsapi.h)
Erstellt einen neuen Prozess und seinen primären Thread. Der neue Prozess wird im Sicherheitskontext des aufrufenden Prozesses ausgeführt.
Wenn der aufrufende Prozess die Identität eines anderen Benutzers angibt, verwendet der neue Prozess das Token für den aufrufenden Prozess, nicht das Identitätswechseltoken. Um den neuen Prozess im Sicherheitskontext des Benutzers auszuführen, der durch das Identitätswechseltoken dargestellt wird, verwenden Sie die CreateProcessAsUserA-Funktion oder CreateProcessWithLogonW-Funktion.
Syntax
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
);
Parameter
[in, optional] lpApplicationName
Der Name des auszuführenden Moduls. Dieses Modul kann eine Windows-basierte Anwendung sein. Es kann sich um einen anderen Modultyp (z. B. MS-DOS oder OS/2) handeln, wenn das entsprechende Subsystem auf dem lokalen Computer verfügbar ist.
Die Zeichenfolge kann den vollständigen Pfad und Dateinamen des auszuführenden Moduls angeben oder einen Teilnamen angeben. Bei einem Teilnamen verwendet die Funktion das aktuelle Laufwerk und das aktuelle Verzeichnis, um die Spezifikation abzuschließen. Die Funktion verwendet nicht den Suchpfad. Dieser Parameter muss die Dateinamenerweiterung enthalten; es wird keine Standarderweiterung angenommen.
Der parameter lpApplicationName kann NULL-sein. In diesem Fall muss der Modulname das erste leerzeichentrennte Token in der lpCommandLine- Zeichenfolge sein. Wenn Sie einen langen Dateinamen verwenden, der ein Leerzeichen enthält, verwenden Sie an zitierte Zeichenfolgen, um anzugeben, wo der Dateiname endet und die Argumente beginnen; andernfalls ist der Dateiname mehrdeutig. Betrachten Sie beispielsweise die Zeichenfolge "c:\program files\sub dir\program name". Diese Zeichenfolge kann auf verschiedene Arten interpretiert werden. Das System versucht, die Möglichkeiten in der folgenden Reihenfolge zu interpretieren:
- c:\program.exe
- c:\program files\sub.exe
- c:\program files\sub dir\program.exe
- c:\program files\sub dir\program name.exe
Wenn das ausführbare Modul eine 16-Bit-Anwendung ist, sollte lpApplicationName-NULL-sein, und die Zeichenfolge, auf die durch lpCommandLine verweist, sollte das ausführbare Modul sowie die zugehörigen Argumente angeben.
Um eine Batchdatei auszuführen, müssen Sie den Befehlsdolmetscher starten. legen Sie lpApplicationName auf cmd.exe fest, und legen Sie lpCommandLine- auf die folgenden Argumente fest: /c plus den Namen der Batchdatei.
Wichtig
Das MSRC Engineering Team berät dagegen. Weitere Informationen finden Sie unter MS14-019 – Reparieren eines binären Entführers über .cmd oder .bat Datei.
[in, out, optional] lpCommandLine
Die auszuführende Befehlszeile.
Die maximale Länge dieser Zeichenfolge beträgt 32.767 Zeichen, einschließlich des Unicode-Endzeichens null. Wenn lpApplicationNameNULL-ist, ist der Modulnameteil lpCommandLine- auf MAX_PATH Zeichen beschränkt.
Die Unicode-Version dieser Funktion, CreateProcessW-, kann den Inhalt dieser Zeichenfolge ändern. Daher kann dieser Parameter kein Zeiger auf schreibgeschützten Speicher sein (z. B. eine Variable oder eine Literalzeichenfolge). Wenn dieser Parameter eine konstante Zeichenfolge ist, kann die Funktion einen Zugriffsverstoß verursachen.
Der parameter lpCommandLine kann NULL sein. In diesem Fall verwendet die Funktion die Zeichenfolge, auf die lpApplicationName als Befehlszeile verweist.
Wenn sowohl lpApplicationName als auch lpCommandLine- nichtNULL-sind, gibt die durch lpApplicationName verweisende Zeichenfolge das auszuführende Modul an, und die durch lpCommandLine hervorgehobene NULL-Zeichenfolge gibt die Befehlszeile an. Der neue Prozess kann GetCommandLine- verwenden, um die gesamte Befehlszeile abzurufen. Konsolenprozesse, die in C geschrieben wurden, können die argc und argv Argumente verwenden, um die Befehlszeile zu analysieren. Da argv[0] der Modulname ist, wiederholen C-Programmierer in der Regel den Modulnamen als erstes Token in der Befehlszeile.
Wenn lpApplicationName NULL ist, gibt das erste durch Leerzeichen getrennte Token der Befehlszeile den Modulnamen an. Wenn Sie einen langen Dateinamen verwenden, der ein Leerzeichen enthält, verwenden Sie Zeichenfolgen, um anzugeben, wo der Dateiname endet und die Argumente beginnen (siehe Erläuterung für den lpApplicationName Parameter). Wenn der Dateiname keine Erweiterung enthält, wird .exe angefügt. Wenn die Dateinamenerweiterung .com ist, muss dieser Parameter daher die .com Erweiterung enthalten. Wenn der Dateiname in einem Punkt (.) ohne Erweiterung endet oder wenn der Dateiname einen Pfad enthält, wird .exe nicht angefügt. Wenn der Dateiname keinen Verzeichnispfad enthält, sucht das System in der folgenden Sequenz nach der ausführbaren Datei:
- Das Verzeichnis, aus dem die Anwendung geladen wurde.
- Das aktuelle Verzeichnis für den übergeordneten Prozess.
- Das 32-Bit-Windows-Systemverzeichnis. Verwenden Sie die GetSystemDirectoryA-Funktion Funktion, um den Pfad dieses Verzeichnisses abzurufen.
- Das 16-Bit-Windows-Systemverzeichnis. Es gibt keine Funktion, die den Pfad dieses Verzeichnisses abruft, aber es wird durchsucht. Der Name dieses Verzeichnisses lautet "System".
- Das Windows-Verzeichnis. Verwenden Sie die GetWindowsDirectoryA-Funktion, um den Pfad dieses Verzeichnisses abzurufen.
- Die Verzeichnisse, die in der PATH-Umgebungsvariable aufgeführt sind. Beachten Sie, dass diese Funktion nicht den vom App-Pfad Registrierungsschlüssel angegebenen Anwendungspfade durchsucht. Um diesen Anwendungspfad in die Suchsequenz einzuschließen, verwenden Sie die ShellExecute-Funktion.
Das System fügt der Befehlszeilenzeichenfolge ein endendes NULL-Zeichen hinzu, um den Dateinamen von den Argumenten zu trennen. Dadurch wird die ursprüngliche Zeichenfolge in zwei Zeichenfolgen für die interne Verarbeitung unterteilt.
[in, optional] lpProcessAttributes
Ein Zeiger auf eine SECURITY_ATTRIBUTES Struktur, die bestimmt, ob das zurückgegebene Handle an das neue Prozessobjekt von untergeordneten Prozessen geerbt werden kann. Wenn lpProcessAttributes-NULL-ist, kann das Handle nicht geerbt werden.
Der lpSecurityDescriptor Mitglied der Struktur gibt einen Sicherheitsdeskriptor für den neuen Prozess an. Wenn lpProcessAttributes- NULL oder lpSecurityDescriptor-NULL-ist, erhält der Prozess einen Standardsicherheitsdeskriptor. Die ACLs im Standardsicherheitsdeskriptor für einen Prozess stammen aus dem primären Token des Erstellers. Windows XP: Die ACLs im Standardsicherheitsdeskriptor für einen Prozess stammen aus dem primären Oder Identitätswechseltoken des Erstellers. Dieses Verhalten wurde mit Windows XP mit SP2 und Windows Server 2003 geändert.
[in, optional] lpThreadAttributes
Ein Zeiger auf eine SECURITY_ATTRIBUTES-Struktur, die bestimmt, ob das zurückgegebene Handle an das neue Threadobjekt von untergeordneten Prozessen geerbt werden kann. Wenn lpThreadAttributes NULL ist, kann das Handle nicht geerbt werden.
Der lpSecurityDescriptor Element der Struktur gibt einen Sicherheitsdeskriptor für den Hauptthread an. Wenn lpThreadAttributes- NULL oder lpSecurityDescript or null ist, erhält der Thread einen Standardsicherheitsdeskriptor. Die ACLs im Standardsicherheitsdeskriptor für einen Thread stammen aus dem Prozesstoken. Windows XP: Die ACLs im Standardsicherheitsdeskriptor für einen Thread stammen aus dem primären Oder Identitätswechseltoken des Erstellers. Dieses Verhalten wurde mit Windows XP mit SP2 und Windows Server 2003 geändert.
[in] bInheritHandles
Wenn dieser Parameter WAHR ist, wird jedes vererbbare Handle im aufrufenden Prozess vom neuen Prozess geerbt. Wenn der Parameter FALSE ist, werden die Handles nicht geerbt. Beachten Sie, dass geerbte Handles denselben Wert und zugriffsrechte wie die ursprünglichen Handles aufweisen. Weitere Erläuterungen zu vererbbaren Handles finden Sie in den Anmerkungen.
Terminaldienste: Sie können keine Handles über Sitzungen hinweg erben. Wenn dieser Parameter TRUE ist, müssen Sie den Prozess in derselben Sitzung wie der Aufrufer erstellen.
Protected Process Light (PPL)-Prozesse: Die generische Handlevererbung wird blockiert, wenn ein PPL-Prozess einen Nicht-PPL-Prozess erstellt, da PROCESS_DUP_HANDLE von einem Nicht-PPL-Prozess zu einem PPL-Prozess nicht zulässig ist. Siehe Prozesssicherheit und Zugriffsrechte
Windows 7: STD_INPUT_HANDLE, STD_OUTPUT_HANDLE und STD_ERROR_HANDLE werden geerbt, auch wenn der Parameter FALSE ist.
[in] dwCreationFlags
Die Flags, die die Prioritätsklasse und die Erstellung des Prozesses steuern. Eine Liste der Werte finden Sie unter Prozesserstellungskennzeichnungen.
Dieser Parameter steuert auch die Prioritätsklasse des neuen Prozesses, die verwendet wird, um die Planungsprioritäten der Threads des Prozesses zu bestimmen. Eine Liste der Werte finden Sie unter GetPriorityClass. Wenn keines der Prioritätsklassenflags angegeben ist, wird die Prioritätsklasse standardmäßig NORMAL_PRIORITY_CLASS, es sei denn, die Prioritätsklasse des Erstellungsprozesses ist IDLE_PRIORITY_CLASS oder BELOW_NORMAL_PRIORITY_CLASS. In diesem Fall empfängt der untergeordnete Prozess die Standardprioritätsklasse des aufrufenden Prozesses.
Wenn der dwCreationFlags-Parameter den Wert 0 hat:
- Der Prozess erbt sowohl den Fehlermodus des Aufrufers als auch die Konsole des übergeordneten Elements.
- Der Umgebungsblock für den neuen Prozess wird als ANSI-Zeichen angenommen (weitere Informationen finden Sie unter lpEnvironment Parameter).
- Eine 16-Bit-Windows-basierte Anwendung wird auf einem freigegebenen virtuellen DOS-Computer (VDM) ausgeführt.
[in, optional] lpEnvironment
Ein Zeiger auf den Umgebungsblock für den neuen Prozess. Wenn dieser Parameter NULL-ist, verwendet der neue Prozess die Umgebung des aufrufenden Prozesses.
Ein Umgebungsblock besteht aus einem null-beendeten Block mit null-beendeten Zeichenfolgen. Jede Zeichenfolge befindet sich in der folgenden Form:
Name=Wert\0
Da das Gleichheitszeichen als Trennzeichen verwendet wird, darf es nicht im Namen einer Umgebungsvariablen verwendet werden.
Ein Umgebungsblock kann unicode- oder ANSI-Zeichen enthalten. Wenn der Umgebungsblock, auf den lpEnvironment verweist, Unicode-Zeichen enthält, stellen Sie sicher, dass dwCreationFlags-CREATE_UNICODE_ENVIRONMENTenthält.
Die ANSI-Version dieser Funktion, CreateProcessA- fehlschlägt, wenn die Gesamtgröße des Umgebungsblocks für den Prozess 32.767 Zeichen überschreitet.
Beachten Sie, dass ein ANSI-Umgebungsblock um zwei Nullbytes beendet wird: eine für die letzte Zeichenfolge, eine weitere zum Beenden des Blocks. Ein Unicode-Umgebungsblock wird durch vier Nullbyte beendet: zwei für die letzte Zeichenfolge, zwei weitere, um den Block zu beenden.
[in, optional] lpCurrentDirectory
Der vollständige Pfad zum aktuellen Verzeichnis für den Prozess. Die Zeichenfolge kann auch einen UNC-Pfad angeben.
Wenn dieser Parameter NULL-ist, weist der neue Prozess dasselbe aktuelle Laufwerk und verzeichnis wie der aufrufende Prozess auf. (Dieses Feature wird hauptsächlich für Shells bereitgestellt, die eine Anwendung starten und das ursprüngliche Laufwerk und das Arbeitsverzeichnis angeben müssen.)
[in] lpStartupInfo
Ein Zeiger auf eine STARTUPINFO-- oder STARTUPINFOEX--Struktur.
Verwenden Sie zum Festlegen erweiterter Attribute eine STARTUPINFOEX- Struktur, und geben Sie EXTENDED_STARTUPINFO_PRESENT im dwCreationFlags-Parameter an.
Handles in STARTUPINFO oder STARTUPINFOEX- müssen mit CloseHandle- geschlossen werden, wenn sie nicht mehr benötigt werden.
Wichtig
Der Aufrufer ist dafür verantwortlich, sicherzustellen, dass die Standardhandlefelder in STARTUPINFO gültige Handlewerte enthalten. Diese Felder werden ohne Überprüfung unverändert in den untergeordneten Prozess kopiert, auch wenn das dwFlags Member STARTF_USESTDHANDLESangibt. Falsche Werte können dazu führen, dass der untergeordnete Prozess falsch ist oder abstürzt. Verwenden Sie das Application Verifier Laufzeitüberprüfungstool, um ungültige Handles zu erkennen.
[out] lpProcessInformation
Ein Zeiger auf eine PROCESS_INFORMATION-Struktur, die Identifikationsinformationen zum neuen Prozess empfängt.
Handles in PROCESS_INFORMATION müssen mit CloseHandle- geschlossen werden, wenn sie nicht mehr benötigt werden.
Rückgabewert
Wenn die Funktion erfolgreich ist, ist der Rückgabewert ungleich Null.
Wenn die Funktion fehlschlägt, ist der Rückgabewert null. Rufen Sie GetLastErrorauf, um erweiterte Fehlerinformationen zu erhalten.
Beachten Sie, dass die Funktion zurückgibt, bevor der Prozess die Initialisierung abgeschlossen hat. Wenn eine erforderliche DLL nicht gefunden werden kann oder nicht initialisiert werden kann, wird der Prozess beendet. Rufen Sie GetExitCodeProcessauf, um den Beendigungsstatus eines Prozesses abzurufen.
Bemerkungen
Dem Prozess wird ein Prozessbezeichner zugewiesen. Der Bezeichner ist gültig, bis der Prozess beendet wird. Sie kann verwendet werden, um den Prozess zu identifizieren oder in der OpenProcess--Funktion anzugeben, um einen Handle für den Prozess zu öffnen. Dem anfänglichen Thread im Prozess wird auch ein Threadbezeichner zugewiesen. Sie kann in der OpenThread--Funktion angegeben werden, um einen Handle für den Thread zu öffnen. Der Bezeichner ist gültig, bis der Thread beendet wird und kann verwendet werden, um den Thread innerhalb des Systems eindeutig zu identifizieren. Diese Bezeichner werden in der PROCESS_INFORMATION-Struktur zurückgegeben.
Der Name der ausführbaren Datei in der Befehlszeile, die das Betriebssystem für einen Prozess bereitstellt, ist nicht unbedingt mit dem in der Befehlszeile identisch, die der aufrufende Prozess der CreateProcess--Funktion bereitstellt. Das Betriebssystem kann einen vollqualifizierten Pfad zu einem ausführbaren Namen vorangestellt haben, der ohne vollqualifizierten Pfad bereitgestellt wird.
Der aufrufende Thread kann die WaitForInputIdle--Funktion verwenden, um zu warten, bis der neue Prozess die Initialisierung abgeschlossen hat und auf benutzereingaben ohne Ausstehend wartet. Dies kann für die Synchronisierung zwischen übergeordneten und untergeordneten Prozessen nützlich sein, da CreateProcess zurückgegeben wird, ohne darauf zu warten, dass der neue Prozess die Initialisierung abgeschlossen hat. Beispielsweise würde der Erstellungsprozess WaitForInputIdle- verwenden, bevor versucht wird, ein Fenster zu finden, das dem neuen Prozess zugeordnet ist.
Die bevorzugte Möglichkeit zum Herunterfahren eines Prozesses ist die Verwendung der ExitProcess--Funktion, da diese Funktion eine Benachrichtigung über die Beendigung an alle DLLs sendet, die an den Prozess angefügt sind. Andere Methoden zum Herunterfahren eines Prozesses benachrichtigen die angefügten DLLs nicht. Beachten Sie, dass andere Threads des Prozesses beendet werden, wenn ein Thread ExitProcessaufruft, ohne dass weitere Code ausgeführt werden kann (einschließlich des Threadendierungscodes von angefügten DLLs). Weitere Informationen finden Sie unter Beenden eines Prozess-.
Ein übergeordneter Prozess kann die Umgebungsvariablen eines untergeordneten Prozesses während der Prozesserstellung direkt ändern. Dies ist die einzige Situation, wenn ein Prozess die Umgebungseinstellungen eines anderen Prozesses direkt ändern kann. Weitere Informationen finden Sie unter Ändern von Umgebungsvariablen.
Wenn eine Anwendung einen Umgebungsblock bereitstellt, werden die aktuellen Verzeichnisinformationen der Systemlaufwerke nicht automatisch an den neuen Prozess weitergegeben. Beispielsweise gibt es eine Umgebungsvariable namens =C: deren Wert das aktuelle Verzeichnis auf Laufwerk C ist. Eine Anwendung muss die aktuellen Verzeichnisinformationen manuell an den neuen Prozess übergeben. Dazu muss die Anwendung diese Umgebungsvariablen-Zeichenfolgen explizit erstellen, alphabetisch sortieren (da das System eine sortierte Umgebung verwendet), und sie in den Umgebungsblock einfügen. Normalerweise werden sie aufgrund der Sortierreihenfolge des Umgebungsblocks an der Vorderseite des Umgebungsblocks angezeigt.
Eine Möglichkeit zum Abrufen der aktuellen Verzeichnisinformationen für ein Laufwerk X besteht darin, den folgenden Aufruf auszuführen: GetFullPathName("X:", ...)
. Dadurch wird verhindert, dass eine Anwendung den Umgebungsblock scannen muss. Wenn der zurückgegebene vollständige Pfad "X:" lautet, muss dieser Wert nicht als Umgebungsdaten übergeben werden, da das Stammverzeichnis das standard aktuelle Verzeichnis für Laufwerk X eines neuen Prozesses ist.
Wenn ein Prozess mit CREATE_NEW_PROCESS_GROUP angegeben erstellt wird, wird ein impliziter Aufruf von SetConsoleCtrlHandler(NULL-,TRUE) im Namen des neuen Prozesses ausgeführt; Dies bedeutet, dass der neue Prozess STRG+C deaktiviert hat. Auf diese Weise können Shells STRG+C selbst verarbeiten und dieses Signal selektiv an Teilprozesse übergeben. STRG+UNTBR ist nicht deaktiviert und kann verwendet werden, um die Prozess-/Prozessgruppe zu unterbrechen.
Standardmäßig bewirkt das Übergeben TRUE- als Wert der bInheritHandles Parameter, dass alle vererbbaren Handles vom neuen Prozess geerbt werden. Dies kann für Anwendungen problematisch sein, die Prozesse aus mehreren Threads gleichzeitig erstellen und dennoch wünschen, dass jeder Prozess verschiedene Handles erbt.
Anwendungen können die UpdateProcThreadAttributeList--Funktion mit dem PROC_THREAD_ATTRIBUTE_HANDLE_LIST-Parameter verwenden, um eine Liste der Handles bereitzustellen, die von einem bestimmten Prozess geerbt werden sollen.
Sicherheitsmerkungen
Der erste Parameter, lpApplicationName, kann NULL-sein. In diesem Fall muss sich der ausführbare Name in der durch lpCommandLinedurch Trennzeichen getrennten Zeichenfolge befinden. Wenn der Name der ausführbaren Datei oder des Pfads ein Leerzeichen enthält, besteht das Risiko, dass eine andere ausführbare Datei aufgrund der Art und Weise ausgeführt werden kann, wie die Funktion Leerzeichen analysiert. Das folgende Beispiel ist gefährlich, da die Funktion versucht, "Program.exe" auszuführen, falls vorhanden, anstelle von "MyApp.exe".
LPTSTR szCmdline = _tcsdup(TEXT("C:\\Program Files\\MyApp -L -S"));
CreateProcess(NULL, szCmdline, /* ... */);
Wenn ein böswilliger Benutzer eine Anwendung namens "Program.exe" auf einem System erstellen würde, führt jedes Programm, das CreateProcess mit dem Verzeichnis "Programme" fälschlicherweise aufruft, diese Anwendung anstelle der beabsichtigten Anwendung aus.
Um dieses Problem zu vermeiden, übergeben Sie nicht NULL- für lpApplicationName. Wenn Sie NULL- für lpApplicationNameübergeben, verwenden Sie Anführungszeichen um den ausführbaren Pfad in lpCommandLine, wie im folgenden Beispiel gezeigt.
LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));
CreateProcess(NULL, szCmdline, /*...*/);
Beispiele
Ein Beispiel finden Sie unter Erstellen von Prozessen.
Anmerkung
Der Processthreadsapi.h-Header definiert CreateProcess als Alias, der automatisch die ANSI- oder Unicode-Version dieser Funktion basierend auf der Definition der UNICODE-Präprozessorkonstante auswählt. Das Mischen der Verwendung des codierungsneutralen Alias mit Code, der nicht codierungsneutral ist, kann zu Nichtübereinstimmungen führen, die zu Kompilierungs- oder Laufzeitfehlern führen. Weitere Informationen finden Sie unter Konventionen für Funktionsprototypen.
Anforderungen
Anforderung | Wert |
---|---|
mindestens unterstützte Client- | Windows XP [Desktop-Apps | UWP-Apps] |
mindestens unterstützte Server- | Windows Server 2003 [Desktop-Apps | UWP-Apps] |
Zielplattform- | Fenster |
Header- | processthreadsapi.h (include Windows.h on Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 Windows Server 2008 R2) |
Library | Kernel32.lib |
DLL- | Kernel32.dll |