Compartir a través de


Función CreateProcessA (processthreadsapi.h)

Crea un nuevo proceso y su subproceso principal. El nuevo proceso se ejecuta en el contexto de seguridad del proceso de llamada.

Si el proceso de llamada suplanta a otro usuario, el nuevo proceso usa el token para el proceso de llamada, no el token de suplantación. Para ejecutar el nuevo proceso en el contexto de seguridad del usuario representado por el token de suplantación, use la función CreateProcessAsUserA o función CreateProcessWithLogonW.

Sintaxis

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

Parámetros

[in, optional] lpApplicationName

Nombre del módulo que se va a ejecutar. Este módulo puede ser una aplicación basada en Windows. Puede ser algún otro tipo de módulo (por ejemplo, MS-DOS o OS/2) si el subsistema adecuado está disponible en el equipo local.

La cadena puede especificar la ruta de acceso completa y el nombre de archivo del módulo que se va a ejecutar o puede especificar un nombre parcial. En el caso de un nombre parcial, la función usa la unidad actual y el directorio actual para completar la especificación. La función no usará la ruta de acceso de búsqueda. Este parámetro debe incluir la extensión de nombre de archivo; no se supone ninguna extensión predeterminada.

El parámetro lpApplicationName puede ser NULL. En ese caso, el nombre del módulo debe ser el primer token de espacio en blanco delimitado en la cadena de lpCommandLine. Si usa un nombre de archivo largo que contiene un espacio, use cadenas entre comillas para indicar dónde finaliza el nombre de archivo y los argumentos comienzan; de lo contrario, el nombre de archivo es ambiguo. Por ejemplo, considere la cadena "c:\program files\sub dir\program name". Esta cadena se puede interpretar de varias maneras. El sistema intenta interpretar las posibilidades en el orden siguiente:

  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 el módulo ejecutable es una aplicación de 16 bits, lpApplicationName debe ser NULLy la cadena a la que apunta lpCommandLine debe especificar el módulo ejecutable, así como sus argumentos.

Para ejecutar un archivo por lotes, debe iniciar el intérprete de comandos; establezca lpApplicationName en cmd.exe y establezca lpCommandLine en los argumentos siguientes: /c más el nombre del archivo por lotes.

Importante

El equipo de ingeniería de MSRC aconseja esto. Consulte MS14-019 – Corregir un secuestro binario a través de .cmd o .bat archivo para obtener más detalles.

[in, out, optional] lpCommandLine

Línea de comandos que se va a ejecutar.

La longitud máxima de esta cadena es de 32 767 caracteres, incluido el carácter NULL de terminación Unicode. Si lpApplicationName es NULL, la parte del nombre del módulo de lpCommandLine se limita a MAX_PATH caracteres.

La versión Unicode de esta función, CreateProcessW, puede modificar el contenido de esta cadena. Por lo tanto, este parámetro no puede ser un puntero a la memoria de solo lectura (como un const variable o una cadena literal). Si este parámetro es una cadena constante, la función puede provocar una infracción de acceso.

El parámetro lpCommandLine puede ser NULL. En ese caso, la función usa la cadena a la que apunta lpApplicationName como línea de comandos.

Si tanto lpApplicationName como lpCommandLine no sonNULL, la cadena terminada en null a la que apunta lpApplicationName especifica el módulo que se va a ejecutar y la cadena terminada en null a la que apunta lpCommandLine especifica la línea de comandos. El nuevo proceso puede usar GetCommandLine para recuperar toda la línea de comandos. Los procesos de consola escritos en C pueden usar el argc de y argumentos argv para analizar la línea de comandos. Dado que argv[0] es el nombre del módulo, los programadores de C suelen repetir el nombre del módulo como el primer token de la línea de comandos.

Si lpApplicationName es NULL, el primer token delimitado por espacios en blanco de la línea de comandos especifica el nombre del módulo. Si usa un nombre de archivo largo que contiene un espacio, use cadenas entre comillas para indicar dónde finaliza el nombre de archivo y los argumentos comienzan (vea la explicación del parámetro lpApplicationName). Si el nombre de archivo no contiene una extensión, se anexa .exe. Por lo tanto, si la extensión de nombre de archivo es .com, este parámetro debe incluir la extensión .com. Si el nombre de archivo finaliza en un punto (.) sin extensión, o si el nombre de archivo contiene una ruta de acceso, .exe no se anexa. Si el nombre de archivo no contiene una ruta de acceso de directorio, el sistema busca el archivo ejecutable en la siguiente secuencia:

  • Directorio desde el que se cargó la aplicación.
  • Directorio actual del proceso primario.
  • Directorio del sistema de Windows de 32 bits. Use la función función GetSystemDirectoryA para obtener la ruta de acceso de este directorio.
  • Directorio del sistema de Windows de 16 bits. No hay ninguna función que obtenga la ruta de acceso de este directorio, pero se busca. El nombre de este directorio es System.
  • Directorio de Windows. Use el función GetWindowsDirectoryA para obtener la ruta de acceso de este directorio.
  • Directorios que aparecen en la variable de entorno PATH. Tenga en cuenta que esta función no busca la ruta de acceso por aplicación especificada por las rutas de acceso de aplicación clave del Registro. Para incluir esta ruta de acceso por aplicación en la secuencia de búsqueda, use la función ShellExecute de .

El sistema agrega un carácter NULO de terminación a la cadena de línea de comandos para separar el nombre de archivo de los argumentos. Esto divide la cadena original en dos cadenas para el procesamiento interno.

[in, optional] lpProcessAttributes

Puntero a una estructura de SECURITY_ATTRIBUTES que determina si los procesos secundarios pueden heredar el identificador devuelto al nuevo objeto de proceso. Si lpProcessAttributes es NULL, no se puede heredar el identificador.

El lpSecurityDescriptor miembro de la estructura especifica un descriptor de seguridad para el nuevo proceso. Si lpProcessAttributes es NULL o lpSecurityDescriptor es NULL, el proceso obtiene un descriptor de seguridad predeterminado. Las ACL del descriptor de seguridad predeterminado para un proceso proceden del token principal del creador. Windows XP: Las ACL del descriptor de seguridad predeterminado para un proceso proceden del token principal o de suplantación del creador. Este comportamiento cambió con Windows XP con SP2 y Windows Server 2003.

[in, optional] lpThreadAttributes

Puntero a una estructura SECURITY_ATTRIBUTES que determina si los procesos secundarios pueden heredar el identificador devuelto al nuevo objeto de subproceso. Si lpThreadAttributes es NULL, no se puede heredar el identificador.

El lpSecurityDescriptor miembro de la estructura especifica un descriptor de seguridad para el subproceso principal. Si lpThreadAttributes es NULL o lpSecurityDescriptor es NULL, el subproceso obtiene un descriptor de seguridad predeterminado. Las ACL del descriptor de seguridad predeterminado para un subproceso proceden del token de proceso. Windows XP: Las ACL del descriptor de seguridad predeterminado de un subproceso proceden del token principal o de suplantación del creador. Este comportamiento cambió con Windows XP con SP2 y Windows Server 2003.

[in] bInheritHandles

Si este parámetro es TRUE, el nuevo proceso hereda cada identificador que se pueda heredar en el proceso de llamada. Si el parámetro es FALSE, los identificadores no se heredan. Tenga en cuenta que los identificadores heredados tienen el mismo valor y derechos de acceso que los identificadores originales. Para obtener más información sobre los identificadores heredables, vea Comentarios.

Terminal Services: no se pueden heredar identificadores entre sesiones. Además, si este parámetro es TRUE, debe crear el proceso en la misma sesión que el autor de la llamada.

procesos de luz de proceso protegido (PPL): La herencia de identificadores genéricos se bloquea cuando un proceso PPL crea un proceso que no es PPL, ya que PROCESS_DUP_HANDLE no se permite desde un proceso que no sea PPL a un proceso PPL. Consulte de seguridad y acceso de procesos de

Windows 7: STD_INPUT_HANDLE, STD_OUTPUT_HANDLE y STD_ERROR_HANDLE se heredan, incluso cuando el parámetro es FALSE.

[in] dwCreationFlags

Marcas que controlan la clase de prioridad y la creación del proceso. Para obtener una lista de valores, consulte Marcas de creación de procesos.

Este parámetro también controla la clase de prioridad del nuevo proceso, que se usa para determinar las prioridades de programación de los subprocesos del proceso. Para obtener una lista de valores, vea GetPriorityClass. Si no se especifica ninguna de las marcas de clase de prioridad, la clase de prioridad tiene como valor predeterminado NORMAL_PRIORITY_CLASS a menos que la clase de prioridad del proceso de creación sea IDLE_PRIORITY_CLASS o BELOW_NORMAL_PRIORITY_CLASS. En este caso, el proceso secundario recibe la clase de prioridad predeterminada del proceso de llamada.

Si el parámetro dwCreationFlags tiene un valor de 0:

  • El proceso hereda el modo de error del autor de la llamada y la consola del elemento primario.
  • Se supone que el bloque de entorno del nuevo proceso contiene caracteres ANSI (consulte parámetro lpEnvironment para obtener información adicional).
  • Una aplicación basada en Windows de 16 bits se ejecuta en una máquina Virtual DOS (VDM) compartida.

[in, optional] lpEnvironment

Puntero al bloque de entorno para el nuevo proceso. Si este parámetro es NULL, el nuevo proceso usa el entorno del proceso de llamada.

Un bloque de entorno consta de un bloque terminado en null de cadenas terminadas en NULL. Cada cadena tiene el formato siguiente:

nombre=valor\0

Dado que el signo igual se usa como separador, no debe usarse en el nombre de una variable de entorno.

Un bloque de entorno puede contener caracteres Unicode o ANSI. Si el bloque de entorno al que apunta lpEnvironment contiene caracteres Unicode, asegúrese de que dwCreationFlags incluye CREATE_UNICODE_ENVIRONMENT.

La versión ANSI de esta función, createProcessA produce un error si el tamaño total del bloque de entorno del proceso supera los 32 767 caracteres.

Tenga en cuenta que un bloque de entorno ANSI finaliza en dos bytes cero: uno para la última cadena, uno más para finalizar el bloque. Un bloque de entorno Unicode finaliza en cuatro bytes cero: dos para la última cadena, dos más para finalizar el bloque.

[in, optional] lpCurrentDirectory

Ruta de acceso completa al directorio actual del proceso. La cadena también puede especificar una ruta de acceso UNC.

Si este parámetro es NULL, el nuevo proceso tendrá la misma unidad y directorio actuales que el proceso de llamada. (Esta característica se proporciona principalmente para los shells que necesitan iniciar una aplicación y especificar su unidad inicial y directorio de trabajo).

[in] lpStartupInfo

Puntero a una estructura de STARTUPINFO o STARTUPINFOEX.

Para establecer atributos extendidos, use una estructura de STARTUPINFOEX y especifique EXTENDED_STARTUPINFO_PRESENT en el parámetro dwCreationFlags.

Los identificadores de STARTUPINFO o STARTUPINFOEX deben cerrarse con CloseHandle cuando ya no sean necesarios.

Importante

El autor de la llamada es responsable de garantizar que los campos de identificador estándar de STARTUPINFO contengan valores de identificador válidos. Estos campos se copian sin cambios en el proceso secundario sin validación, incluso cuando el miembro dwFlags especifica STARTF_USESTDHANDLES. Los valores incorrectos pueden hacer que el proceso secundario se comporte o bloquee mal. Use la herramienta de comprobación del entorno de ejecución comprobador de aplicaciones de para detectar identificadores no válidos.

[out] lpProcessInformation

Puntero a una estructura de PROCESS_INFORMATION que recibe información de identificación sobre el nuevo proceso.

Los identificadores de PROCESS_INFORMATION deben cerrarse con closeHandle cuando ya no sean necesarios.

Valor devuelto

Si la función se ejecuta correctamente, el valor devuelto es distinto de cero.

Si se produce un error en la función, el valor devuelto es cero. Para obtener información de error extendida, llame a GetLastError.

Tenga en cuenta que la función devuelve antes de que el proceso haya terminado de inicializarse. Si no se puede encontrar un archivo DLL necesario o no se puede inicializar, se finaliza el proceso. Para obtener el estado de finalización de un proceso, llame a GetExitCodeProcess.

Observaciones

Al proceso se le asigna un identificador de proceso. El identificador es válido hasta que finaliza el proceso. Se puede usar para identificar el proceso o especificarse en la función OpenProcess para abrir un identificador para el proceso. Al subproceso inicial del proceso también se le asigna un identificador de subproceso. Se puede especificar en la función OpenThread para abrir un identificador en el subproceso. El identificador es válido hasta que finaliza el subproceso y se puede usar para identificar de forma única el subproceso dentro del sistema. Estos identificadores se devuelven en la estructura PROCESS_INFORMATION.

El nombre del archivo ejecutable en la línea de comandos que proporciona el sistema operativo a un proceso no es necesariamente idéntico al de la línea de comandos que el proceso de llamada proporciona a la función CreateProcess. El sistema operativo puede anteponer una ruta de acceso completa a un nombre ejecutable que se proporciona sin una ruta de acceso completa.

El subproceso de llamada puede usar la función WaitForInputIdle para esperar hasta que el nuevo proceso haya terminado su inicialización y esté esperando la entrada del usuario sin entrada pendiente. Esto puede ser útil para la sincronización entre los procesos primarios y secundarios, ya que CreateProcess devuelve sin esperar a que el nuevo proceso finalice su inicialización. Por ejemplo, el proceso de creación usaría WaitForInputIdle antes de intentar encontrar una ventana asociada al nuevo proceso.

La manera preferida de apagar un proceso es mediante el uso de la función exitProcess , ya que esta función envía una notificación de terminación cercana a todos los archivos DLL adjuntos al proceso. Otros medios de apagar un proceso no notifican a los archivos DLL adjuntos. Tenga en cuenta que cuando un subproceso llama a ExitProcess, otros subprocesos del proceso se finalizan sin la oportunidad de ejecutar ningún código adicional (incluido el código de terminación del subproceso de archivos DLL adjuntos). Para obtener más información, consulte Terminación de un proceso.

Un proceso primario puede modificar directamente las variables de entorno de un proceso secundario durante la creación del proceso. Esta es la única situación cuando un proceso puede cambiar directamente la configuración del entorno de otro proceso. Para obtener más información, consulte Cambiar variables de entorno.

Si una aplicación proporciona un bloque de entorno, la información del directorio actual de las unidades del sistema no se propaga automáticamente al nuevo proceso. Por ejemplo, hay una variable de entorno denominada =C: cuyo valor es el directorio actual de la unidad C. Una aplicación debe pasar manualmente la información del directorio actual al nuevo proceso. Para ello, la aplicación debe crear explícitamente estas cadenas de variables de entorno, ordenarlas alfabéticamente (porque el sistema usa un entorno ordenado) y colocarlas en el bloque de entorno. Normalmente, van al principio del bloque de entorno, debido al criterio de ordenación del bloque de entorno.

Una manera de obtener la información del directorio actual de una unidad X es realizar la siguiente llamada: GetFullPathName("X:", ...). Esto evita que una aplicación tenga que examinar el bloque de entorno. Si la ruta de acceso completa devuelta es X:, no es necesario pasar ese valor como datos de entorno, ya que el directorio raíz es el directorio actual predeterminado para la unidad X de un nuevo proceso.

Cuando se crea un proceso con CREATE_NEW_PROCESS_GROUP especificado, se realiza una llamada implícita a SetConsoleCtrlHandler(NULL,TRUE) en nombre del nuevo proceso; esto significa que el nuevo proceso tiene CTRL+C deshabilitado. Esto permite que los shells controlen CTRL+C y pasen de forma selectiva esa señal a los subprocesos. CTRL+BREAK no está deshabilitado y se puede usar para interrumpir el grupo de procesos o procesos.

De forma predeterminada, pasar TRUE como valor del parámetro bInheritHandles hace que el nuevo proceso herede todos los identificadores heredados. Esto puede ser problemático para las aplicaciones que crean procesos a partir de varios subprocesos simultáneamente pero desean que cada proceso herede distintos identificadores.

Las aplicaciones pueden usar la función UpdateProcThreadAttributeList updateProcThreadAttributeList con el parámetro PROC_THREAD_ATTRIBUTE_HANDLE_LIST para proporcionar una lista de identificadores que un proceso determinado hereda.

Comentarios de seguridad

El primer parámetro, lpApplicationName, puede ser NULL, en cuyo caso el nombre ejecutable debe estar en la cadena delimitada por espacios en blanco a la que apunta lpCommandLine. Si el nombre del archivo ejecutable o la ruta de acceso tiene un espacio en él, existe el riesgo de que se pueda ejecutar un archivo ejecutable diferente debido a la forma en que la función analiza los espacios. El ejemplo siguiente es peligroso porque la función intentará ejecutar "Program.exe", si existe, en lugar de "MyApp.exe".

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

Si un usuario malintencionado creara una aplicación denominada "Program.exe" en un sistema, cualquier programa que llame incorrectamente a CreateProcess mediante el directorio Archivos de programa ejecutará esta aplicación en lugar de la aplicación deseada.

Para evitar este problema, no pase NULL para lpApplicationName. Si pasa NULL para lpApplicationName, use comillas alrededor de la ruta de acceso ejecutable en lpCommandLine, como se muestra en el ejemplo siguiente.

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

Ejemplos

Para obtener un ejemplo, vea Creating Processes.

Nota

El encabezado processthreadsapi.h define CreateProcess como alias que selecciona automáticamente la versión ANSI o Unicode de esta función en función de la definición de la constante de preprocesador UNICODE. La combinación del uso del alias neutral de codificación con código que no es neutral de codificación puede dar lugar a errores de coincidencia que dan lugar a errores de compilación o tiempo de ejecución. Para obtener más información, vea Conventions for Function Prototypes.

Requisitos

Requisito Valor
cliente mínimo admitido Windows XP [aplicaciones de escritorio | Aplicaciones para UWP]
servidor mínimo admitido Windows Server 2003 [aplicaciones de escritorio | Aplicaciones para UWP]
de la plataforma de destino de Windows
encabezado de processthreadsapi.h (incluya Windows.h en Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 Windows Server 2008 R2)
biblioteca de Kernel32.lib
DLL de Kernel32.dll

Consulte también

CloseHandle

shellExecuteA

CreateProcessAsUser

CreateProcessWithLogonW

ExitProcess

GetCommandLine

GetEnvironmentStrings

GetExitCodeProcess

GetFullPathName

GetStartupInfo

openProcess

PROCESS_INFORMATION

funciones de proceso y subproceso de

procesos

SECURITY_ATTRIBUTES

STARTUPINFO

STARTUPINFOEX

SetErrorMode

TerminateProcess

WaitForInputIdle