Partage via


Fonction CreateProcessW (processthreadsapi.h)

Crée un processus et son thread principal. Le nouveau processus s’exécute dans le contexte de sécurité du processus appelant.

Si le processus appelant emprunte l’identité d’un autre utilisateur, le nouveau processus utilise le jeton pour le processus appelant, et non le jeton d’emprunt d’identité. Pour exécuter le nouveau processus dans le contexte de sécurité de l’utilisateur représenté par le jeton d’emprunt d’identité, utilisez la fonction CreateProcessAsUser ou CreateProcessWithLogonW .

Syntaxe

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
);

Paramètres

[in, optional] lpApplicationName

Nom du module à exécuter. Ce module peut être une application Windows. Il peut s’agir d’un autre type de module (par exemple, MS-DOS ou OS/2) si le sous-système approprié est disponible sur l’ordinateur local.

La chaîne peut spécifier le chemin d’accès complet et le nom de fichier du module à exécuter ou spécifier un nom partiel. Dans le cas d’un nom partiel, la fonction utilise le lecteur actuel et le répertoire actif pour terminer la spécification. La fonction n’utilise pas le chemin de recherche. Ce paramètre doit inclure l’extension de nom de fichier ; aucune extension par défaut n’est supposée.

Le paramètre lpApplicationName peut être NULL. Dans ce cas, le nom du module doit être le premier jeton délimité par des espaces blancs dans la chaîne lpCommandLine . Si vous utilisez un nom de fichier long qui contient un espace, utilisez des chaînes entre guillemets pour indiquer où le nom de fichier se termine et où les arguments commencent ; sinon, le nom de fichier est ambigu. Par exemple, considérez la chaîne « c :\program files\sub dir\program name ». Cette chaîne peut être interprétée de plusieurs façons. Le système tente d’interpréter les possibilités dans l’ordre suivant :

  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

Si le module exécutable est une application 16 bits, lpApplicationName doit avoir la valeur NULL et la chaîne pointée par lpCommandLine doit spécifier le module exécutable ainsi que ses arguments.

Pour exécuter un fichier batch, vous devez démarrer l’interpréteur de commandes ; définissez lpApplicationName sur cmd.exe et définissez lpCommandLine sur les arguments suivants : /c plus le nom du fichier batch.

[in, out, optional] lpCommandLine

Ligne de commande à exécuter.

La longueur maximale de cette chaîne est de 32 767 caractères, y compris le caractère null de fin Unicode. Si lpApplicationName a la valeur NULL, la partie du nom de module de lpCommandLine est limitée à MAX_PATH caractères.

La version Unicode de cette fonction, CreateProcessW, peut modifier le contenu de cette chaîne. Par conséquent, ce paramètre ne peut pas être un pointeur vers la mémoire en lecture seule (par exemple, une variable const ou une chaîne littérale). Si ce paramètre est une chaîne constante, la fonction peut provoquer une violation d’accès.

Le paramètre lpCommandLine peut être NULL. Dans ce cas, la fonction utilise la chaîne pointée vers lpApplicationName comme ligne de commande.

Si lpApplicationName et lpCommandLine ne sont pas NULL, la chaîne null pointée par lpApplicationName spécifie le module à exécuter et la chaîne terminée par null pointée par lpCommandLine spécifie la ligne de commande. Le nouveau processus peut utiliser GetCommandLine pour récupérer l’intégralité de la ligne de commande. Les processus de console écrits en C peuvent utiliser les arguments argc et argv pour analyser la ligne de commande. Étant donné que argv[0] est le nom du module, les programmeurs C répètent généralement le nom du module comme premier jeton dans la ligne de commande.

Si lpApplicationName a la valeur NULL, le premier jeton délimité par des espaces blancs de la ligne de commande spécifie le nom du module. Si vous utilisez un nom de fichier long qui contient un espace, utilisez des chaînes entre guillemets pour indiquer où le nom de fichier se termine et où les arguments commencent (voir l’explication du paramètre lpApplicationName ). Si le nom de fichier ne contient pas d’extension, .exe est ajouté. Par conséquent, si l’extension de nom de fichier est .com, ce paramètre doit inclure l’extension .com. Si le nom de fichier se termine par un point (.) sans extension, ou si le nom de fichier contient un chemin d’accès, .exe n’est pas ajouté. Si le nom de fichier ne contient pas de chemin de répertoire, le système recherche le fichier exécutable dans l’ordre suivant :

  1. Répertoire à partir duquel l’application a été chargée.
  2. Répertoire actif du processus parent.
  3. Répertoire système Windows 32 bits. Utilisez la fonction GetSystemDirectory pour obtenir le chemin d’accès de ce répertoire.
  4. Répertoire système Windows 16 bits. Aucune fonction n’obtient le chemin d’accès de ce répertoire, mais elle fait l’objet d’une recherche. Le nom de ce répertoire est System.
  5. Répertoire Windows. Utilisez la fonction GetWindowsDirectory pour obtenir le chemin d’accès de ce répertoire.
  6. Répertoires répertoriés dans la variable d’environnement PATH. Notez que cette fonction ne recherche pas le chemin d’accès par application spécifié par la clé de Registre Chemins d’accès d’application . Pour inclure ce chemin d’accès par application dans la séquence de recherche, utilisez la fonction ShellExecute .
Le système ajoute un caractère null de fin à la chaîne de ligne de commande pour séparer le nom de fichier des arguments. Cela divise la chaîne d’origine en deux chaînes pour le traitement interne.

[in, optional] lpProcessAttributes

Pointeur vers une structure de SECURITY_ATTRIBUTES qui détermine si le handle retourné au nouvel objet de processus peut être hérité par les processus enfants. Si lpProcessAttributes a la valeur NULL, le handle ne peut pas être hérité.

Le membre lpSecurityDescriptor de la structure spécifie un descripteur de sécurité pour le nouveau processus. Si lpProcessAttributes a la valeur NULL ou si lpSecurityDescriptor a la valeur NULL, le processus obtient un descripteur de sécurité par défaut. Les listes de contrôle d’accès dans le descripteur de sécurité par défaut d’un processus proviennent du jeton principal du créateur. Windows XP : Les listes de contrôle d’accès dans le descripteur de sécurité par défaut d’un processus proviennent du jeton principal ou d’emprunt d’identité du créateur. Ce comportement a changé avec Windows XP avec SP2 et Windows Server 2003.

[in, optional] lpThreadAttributes

Pointeur vers une structure SECURITY_ATTRIBUTES qui détermine si le handle retourné à l’objet thread peut être hérité par les processus enfants. Si lpThreadAttributes a la valeur NULL, le handle ne peut pas être hérité.

Le membre lpSecurityDescriptor de la structure spécifie un descripteur de sécurité pour le thread main. Si lpThreadAttributes a la valeur NULL ou si lpSecurityDescriptor a la valeur NULL, le thread obtient un descripteur de sécurité par défaut. Les listes de contrôle d’accès dans le descripteur de sécurité par défaut d’un thread proviennent du jeton de processus. Windows XP : Les listes de contrôle d’accès dans le descripteur de sécurité par défaut d’un thread proviennent du jeton principal ou d’emprunt d’identité du créateur. Ce comportement a changé avec Windows XP avec SP2 et Windows Server 2003.

[in] bInheritHandles

Si ce paramètre a la valeur TRUE, chaque handle pouvant être hérité dans le processus appelant est hérité par le nouveau processus. Si le paramètre a la valeur FALSE, les handles ne sont pas hérités. Notez que les handles hérités ont la même valeur et les mêmes droits d’accès que les handles d’origine. Pour plus d’informations sur les handles pouvant être hérités, consultez Remarques.

Services Terminal Server : Vous ne pouvez pas hériter de handles entre les sessions. En outre, si ce paramètre a la valeur TRUE, vous devez créer le processus dans la même session que l’appelant.

Processus PPL (Protected Process Light) : L’héritage de handle générique est bloqué lorsqu’un processus PPL crée un processus non-PPL, car PROCESS_DUP_HANDLE n’est pas autorisé d’un processus non PPL à un processus PPL. Consultez Sécurité des processus et droits d’accès

[in] dwCreationFlags

Indicateurs qui contrôlent la classe de priorité et la création du processus. Pour obtenir la liste des valeurs, consultez Indicateurs de création de processus.

Ce paramètre contrôle également la classe de priorité du nouveau processus, qui est utilisée pour déterminer les priorités de planification des threads du processus. Pour obtenir la liste des valeurs, consultez GetPriorityClass. Si aucun indicateur de classe de priorité n’est spécifié, la classe de priorité est par défaut NORMAL_PRIORITY_CLASS , sauf si la classe de priorité du processus de création est IDLE_PRIORITY_CLASS ou BELOW_NORMAL_PRIORITY_CLASS. Dans ce cas, le processus enfant reçoit la classe de priorité par défaut du processus appelant.

Si le paramètre dwCreationFlags a la valeur 0 :

  • Le processus hérite à la fois du mode d’erreur de l’appelant et de la console parente.
  • Le bloc d’environnement du nouveau processus est supposé contenir des caractères ANSI (pour plus d’informations, consultez le paramètre lpEnvironment ).
  • Une application Windows 16 bits s’exécute sur une machine Virtual DOS (VDM) partagée.

[in, optional] lpEnvironment

Pointeur vers le bloc d’environnement pour le nouveau processus. Si ce paramètre a la valeur NULL, le nouveau processus utilise l’environnement du processus appelant.

Un bloc d’environnement se compose d’un bloc null de chaînes terminées par null. Chaque chaîne se présente sous la forme suivante :

Nom=value\0

Étant donné que le signe égal est utilisé comme séparateur, il ne doit pas être utilisé dans le nom d’une variable d’environnement.

Un bloc d’environnement peut contenir des caractères Unicode ou ANSI. Si le bloc d’environnement pointé vers lpEnvironment contient des caractères Unicode, assurez-vous que dwCreationFlags inclut CREATE_UNICODE_ENVIRONMENT.

La version ANSI de cette fonction , CreateProcessA , échoue si la taille totale du bloc d’environnement pour le processus dépasse 32 767 caractères.

Notez qu’un bloc d’environnement ANSI est terminé par deux octets zéro : un pour la dernière chaîne, un autre pour terminer le bloc. Un bloc d’environnement Unicode est terminé par quatre octets zéro : deux pour la dernière chaîne, deux autres pour terminer le bloc.

[in, optional] lpCurrentDirectory

Chemin d’accès complet au répertoire actif du processus. La chaîne peut également spécifier un chemin UNC.

Si ce paramètre a la valeur NULL, le nouveau processus aura le même lecteur et le même répertoire actuels que le processus appelant. (Cette fonctionnalité est fournie principalement pour les interpréteurs de commandes qui doivent démarrer une application et spécifier son lecteur initial et son répertoire de travail.)

[in] lpStartupInfo

Pointeur vers une structure STARTUPINFO ou STARTUPINFOEX .

Pour définir des attributs étendus, utilisez une structure STARTUPINFOEX et spécifiez EXTENDED_STARTUPINFO_PRESENT dans le paramètre dwCreationFlags .

Les handles dans STARTUPINFO ou STARTUPINFOEX doivent être fermés avec CloseHandle lorsqu’ils ne sont plus nécessaires.

Important L’appelant est chargé de s’assurer que les champs de handle standard dans STARTUPINFO contiennent des valeurs de handle valides. Ces champs sont copiés de manière inchangée dans le processus enfant sans validation, même lorsque le membre dwFlags spécifie STARTF_USESTDHANDLES. Des valeurs incorrectes peuvent entraîner un mauvais comportement ou un blocage du processus enfant. Utilisez l’outil de vérification du runtime Du vérificateur d’application pour détecter les handles non valides.
 

[out] lpProcessInformation

Pointeur vers une structure de PROCESS_INFORMATION qui reçoit des informations d’identification sur le nouveau processus.

Les handles dans PROCESS_INFORMATION doivent être fermés avec CloseHandle lorsqu’ils ne sont plus nécessaires.

Valeur retournée

Si la fonction réussit, la valeur de retour est différente de zéro.

Si la fonction échoue, la valeur de retour est égale à zéro. Pour obtenir des informations détaillées sur l’erreur, appelez GetLastError.

Notez que la fonction retourne avant la fin de l’initialisation du processus. Si une DLL requise ne peut pas être trouvée ou ne parvient pas à s’initialiser, le processus est terminé. Pour obtenir le status d’arrêt d’un processus, appelez GetExitCodeProcess.

Remarques

Un identificateur de processus est affecté au processus. L’identificateur est valide jusqu’à ce que le processus se termine. Il peut être utilisé pour identifier le processus ou spécifié dans la fonction OpenProcess pour ouvrir un handle au processus. Un identificateur de thread est également attribué au thread initial du processus. Il peut être spécifié dans la fonction OpenThread pour ouvrir un handle sur le thread. L’identificateur est valide jusqu’à ce que le thread se termine et peut être utilisé pour identifier de manière unique le thread dans le système. Ces identificateurs sont retournés dans la structure PROCESS_INFORMATION .

Le nom de l’exécutable dans la ligne de commande que le système d’exploitation fournit à un processus n’est pas nécessairement identique à celui de la ligne de commande que le processus appelant donne à la fonction CreateProcess . Le système d’exploitation peut ajouter un chemin complet à un nom exécutable fourni sans chemin complet.

Le thread appelant peut utiliser la fonction WaitForInputIdle pour attendre que le nouveau processus ait terminé son initialisation et qu’il attende l’entrée de l’utilisateur sans aucune entrée en attente. Cela peut être utile pour la synchronisation entre les processus parent et enfant, car CreateProcess retourne sans attendre que le nouveau processus termine son initialisation. Par exemple, le processus de création utilise WaitForInputIdle avant d’essayer de trouver une fenêtre associée au nouveau processus.

La méthode recommandée pour arrêter un processus consiste à utiliser la fonction ExitProcess , car cette fonction envoie une notification d’approche de l’arrêt à toutes les DLL attachées au processus. Les autres moyens d’arrêter un processus n’informent pas les DLL jointes. Notez que lorsqu’un thread appelle ExitProcess, d’autres threads du processus sont arrêtés sans possibilité d’exécuter de code supplémentaire (y compris le code d’arrêt de thread des DLL attachées). Pour plus d’informations, consultez Fin d’un processus.

Un processus parent peut modifier directement les variables d’environnement d’un processus enfant lors de la création du processus. Il s’agit de la seule situation où un processus peut modifier directement les paramètres d’environnement d’un autre processus. Pour plus d’informations, consultez Modification des variables d’environnement.

Si une application fournit un bloc d’environnement, les informations de répertoire actuelles des lecteurs système ne sont pas propagées automatiquement au nouveau processus. Par exemple, il existe une variable d’environnement nommée =C : dont la valeur est le répertoire actuel sur le lecteur C. Une application doit transmettre manuellement les informations du répertoire actif au nouveau processus. Pour ce faire, l’application doit créer explicitement ces chaînes de variables d’environnement, les trier par ordre alphabétique (car le système utilise un environnement trié) et les placer dans le bloc d’environnement. En règle générale, ils passent à l’avant du bloc d’environnement, en raison de l’ordre de tri du bloc d’environnement.

L’un des moyens d’obtenir les informations actuelles sur le répertoire d’un lecteur X consiste à effectuer l’appel suivant : GetFullPathName("X:", ...). Cela évite à une application d’analyser le bloc d’environnement. Si le chemin d’accès complet retourné est X :, il n’est pas nécessaire de transmettre cette valeur en tant que données d’environnement, car le répertoire racine est le répertoire actif par défaut pour le lecteur X d’un nouveau processus.

Lorsqu’un processus est créé avec CREATE_NEW_PROCESS_GROUP spécifié, un appel implicite à SetConsoleCtrlHandler(NULL,TRUE) est effectué au nom du nouveau processus ; cela signifie que ctrl+C est désactivé pour le nouveau processus. Cela permet aux interpréteurs de commandes de gérer eux-mêmes CTRL+C et de transmettre de manière sélective ce signal aux sous-processus. Ctrl+Arrêt n’est pas désactivé et peut être utilisé pour interrompre le groupe processus/processus.

Par défaut, la transmission de TRUE comme valeur du paramètre bInheritHandles entraîne l’héritage de tous les handles pouvant être hérités par le nouveau processus. Cela peut être problématique pour les applications qui créent des processus à partir de plusieurs threads simultanément, mais qui souhaitent que chaque processus hérite de différents handles. Les applications peuvent utiliser la fonction UpdateProcThreadAttributeList avec le paramètre PROC_THREAD_ATTRIBUTE_HANDLE_LIST pour fournir une liste de handles à hériter par un processus particulier.

Remarques sur la sécurité

Le premier paramètre, lpApplicationName, peut être NULL, auquel cas le nom de l’exécutable doit se trouver dans la chaîne délimitée par les espaces blancs pointée par lpCommandLine. Si le nom de l’exécutable ou du chemin d’accès contient un espace, il existe un risque qu’un autre exécutable puisse être exécuté en raison de la façon dont la fonction analyse les espaces. L’exemple suivant est dangereux, car la fonction tente d’exécuter « Program.exe », s’il existe, au lieu de « MyApp.exe ».
	LPTSTR szCmdline = _tcsdup(TEXT("C:\\Program Files\\MyApp -L -S"));
	CreateProcess(NULL, szCmdline, /* ... */);

Si un utilisateur malveillant devait créer une application appelée « Program.exe » sur un système, tout programme qui appelle incorrectement CreateProcess à l’aide du répertoire Program Files exécutera cette application au lieu de l’application prévue.

Pour éviter ce problème, ne passez pas null pour lpApplicationName. Si vous passez la valeur NULL pour lpApplicationName, utilisez des guillemets autour du chemin d’accès exécutable dans lpCommandLine, comme illustré dans l’exemple ci-dessous.

	LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));
	CreateProcess(NULL, szCmdline, /*...*/);

Exemples

Pour obtenir un exemple, consultez Création de processus.

Notes

L’en-tête processthreadsapi.h définit CreateProcess comme un alias qui sélectionne automatiquement la version ANSI ou Unicode de cette fonction en fonction de la définition de la constante de préprocesseur UNICODE. Le mélange de l’utilisation de l’alias neutre en encodage avec du code qui n’est pas neutre en encodage peut entraîner des incompatibilités qui entraînent des erreurs de compilation ou d’exécution. Pour plus d’informations, consultez Conventions pour les prototypes de fonction.

Configuration requise

Condition requise Valeur
Client minimal pris en charge Windows XP [applications de bureau | applications UWP]
Serveur minimal pris en charge Windows Server 2003 [applications de bureau | applications UWP]
Plateforme cible Windows
En-tête processthreadsapi.h (inclure Windows.h sur Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 Windows Server 2008 R2)
Bibliothèque Kernel32.lib
DLL Kernel32.dll

Voir aussi

CloseHandle

ShellExecuteW

CreateProcessAsUser

CreateProcessWithLogonW

ExitProcess

GetCommandLine

GetEnvironmentStrings

GetExitCodeProcess

GetFullPathName

GetStartupInfo

OpenProcess

PROCESS_INFORMATION

Fonctions de processus et de thread

Processus

SECURITY_ATTRIBUTES

STARTUPINFO

STARTUPINFOEX

SetErrorMode

TerminateProcess

WaitForInputIdle