CreateProcess

【勇芳软件工作室】汉化HomePreviousNext

CreateProcess函数创建一个新进程及其主线程。新进程执行指定的可执行文件。

BOOL CreateProcess(

LPCTSTR 【lpApplicationName】,//指向可执行模块名称的指针
LPTSTR 【lpCommandLine】,//指向命令行字符串的指针
LPSECURITY_ATTRIBUTES 【lpProcessAttributes】,//指向进程安全属性的指针
LPSECURITY_ATTRIBUTES 【lpThreadAttributes】,//指向线程安全属性的指针
BOOL 【bInheritHandles】,//处理继承标志
DWORD 【dwCreationFlags】,//创建标志
LPVOID 【// pointer to new environment block】,//指向新的环境块
LPCTSTR 【lpCurrentDirectory】,//指向当前目录名称的指针
LPSTARTUPINFO 【lpStartupInfo】,//指向STARTUPINFO的指针
LPPROCESS_INFORMATION 【lpProcessInformation】//指向PROCESS_INFORMATION的指针
); 

参数

【lpApplicationName】

指向指定要执行的模块的以空值终止的字符串的指针。

该字符串可以指定要执行的模块的完整路径和文件名。

字符串可以指定部分名称。在这种情况下,该函数使用当前驱动器和当前目录来完成规范。

【lpApplicationName】参数可以为NULL。在这种情况下,模块名称必须是【lpCommandLine】字符串中第一个以空格为空的分隔符号。

指定的模块可以是基于Win32的应用程序。如果本地计算机上有适当的子系统可用,它可以是其他类型的模块(例如,MS-DOS或OS / 2)。

Windows NT:如果可执行模块是16位应用程序,【lpApplicationName】应为NULL,并且【lpCommandLine】指向的字符串应指定可执行模块。16位应用程序是作为VDM或WOW进程执行的应用程序。

【lpCommandLine】

指向指定要执行的命令行的以空值终止的字符串的指针。

【lpCommandLine】参数可以为NULL。在这种情况下,该函数使用【lpApplicationName】指向的字符串作为命令行。

如果【lpApplicationName】【lpCommandLine】都不为空,则* 【lpApplicationName】指定要执行的模块,* 【lpCommandLine】指定命令行。新进程可以使用GetCommandLine检索整个命令行。C运行时进程可以使用ARGCARGV参数。

如果【lpApplicationName】为NULL,则命令行的第一个以空白为空的分隔符号指定模块名称。如果文件名不包含扩展名,则假定为.EXE。如果文件名以不带扩展名的句点(。)结尾,或者文件名包含路径,则不附加.EXE。如果文件名不包含目录路径,Windows将按以下顺序搜索可执行文件:

1.应用程序加载的目录。

2.父进程的当前目录。

3.Windows 95: Windows系统目录。使用GetSystemDirectory函数获取此目录的路径。

Windows NT: 32位Windows系统目录。使用GetSystemDirectory函数获取此目录的路径。该目录的名称是SYSTEM32。

4.Windows NT: 16位Windows系统目录。没有获取此目录的路径的Win32函数,但它被搜索。该目录的名称是SYSTEM。

5.Windows目录。使用GetWindowsDirectory函数获取此目录的路径。

6. PATH环境变量中列出的目录。

如果要创建的进程是基于MS-DOS或基于Windows的应用程序,则【lpCommandLine】应该是一个完整的命令行,其中第一个元素是应用程序名称。因为这也适用于基于Win32的应用程序,它是设置【lpCommandLine】的最强大的方法。

【lpProcessAttributes】

指向SECURITY_ATTRIBUTES结构的指针,用于确定返回的句柄是否可由子进程继承。如果【lpProcessAttributes】为NULL,则无法继承该句柄。

Windows NT:结构的lpSecurityDescriptor成员指定新进程的安全描述符。如果【lpProcessAttributes】为NULL,则进程将获得默认安全描述符。

Windows 95:结构的lpSecurityDescriptor成员将被忽略。

【lpThreadAttributes】

指向SECURITY_ATTRIBUTES结构的指针,用于确定返回的句柄是否可由子进程继承。如果【lpThreadAttributes】为NULL,则无法继承句柄。

Windows NT:结构的lpSecurityDescriptor成员指定主线程的安全描述符。如果【lpThreadAttributes】为NULL,线程将获得默认的安全描述符。

Windows 95:结构的lpSecurityDescriptor成员将被忽略。

【bInheritHandles】

指示新进程是否继承来自调用进程的句柄。如果为TRUE,则调用进程中的每个可继承的打开句柄都由新进程继承。继承的句柄具有与原始句柄相同的值和访问权限。

【dwCreationFlags】

指定控制优先级类和进程创建的附加标志。可以以任何组合指定以下创建标志,除非另有说明:

含义
CREATE_DEFAULT_ERROR_MODE 
 新进程不会继承调用进程的错误模式。相反,CreateProcess给新进程当前的默认错误模式。应用程序通过调用SetErrorMode来设置当前的默认错误模式。

此标志对于禁用硬错误运行的多线程shell应用程序特别有用。

CreateProcess的默认行为是新进程继承调用方的错误模式。设置此标志会更改该默认行为。

CREATE_NEW_CONSOLE 
 新进程有一个新的控制台,而不是继承父控制台。该标志不能与DETACHED_PROCESS标志一起使用。
CREATE_NEW_PROCESS_GROUP 
 新进程是新进程组的根进程。进程组包括作为此根进程的后代的所有进程。新进程组的进程标识符与【lpProcessInformation】参数中返回的进程标识符相同。GenerateConsoleCtrlEvent函数使用进程组来启用向一组控制台进程发送CTRL + C或CTRL + BREAK信号。
CREATE_SEPARATE_WOW_VDM 
 仅Windows NT:此标志仅在启动基于Windows的16位应用程序时有效。默认情况下,所有16位基于Windows的应用程序都作为单个共享VDM中的线程运行。单独运行的优点是崩溃只能杀死单个VDM;在不同VDM中运行的任何其他程序继续正常运行。而且,在单独的VDM中运行的16位基于Windows的应用程序具有单独的输入队列。这意味着如果一个应用程序暂时挂起,单独VDM中的应用程序将继续接收输入。
CREATE_SHARED_WOW_VDM 
 仅Windows NT:该标志仅在启动16位基于Windows的应用程序时有效。如果WIN.INI的Windows部分中的DefaultSeparateVDM开关为TRUE,则此标志使CreateProcess功能覆盖交换机,并在共享的虚拟DOS机器中运行新进程。
CREATE_SUSPENDED 
 新进程的主线程被创建为挂起状态,直到调用ResumeThread函数才会运行。
CREATE_UNICODE_ENVIRONMENT 
 如果设置,【// pointer to new environment block】指向的环境块使用Unicode字符。如果清除,则环境块使用ANSI字符。
DEBUG_PROCESS 
 如果设置了此标志,调用进程将被视为调试器,新进程正在被调试。系统通知调试器正在调试的进程中发生的所有调试事件。

如果创建一个设置了该标志的进程,只有调用线程(调用CreateProcess的线程)可以调用WaitForDebugEvent函数。

DEBUG_ONLY_THIS_PROCESS 
 如果未设置并调用调用进程,则新进程将成为调用进程调试器调试的另一进程。如果调用进程不是正在调试的进程,则不会发生与调试相关的操作。
DETACHED_PROCESS 
 对于控制台进程,新进程无法访问父进程的控制台。新进程可以稍后调用AllocConsole函数来创建一个新的控制台。该标志不能与CREATE_NEW_CONSOLE标志一起使用。

【dwCreationFlags】参数还控制新进程的优先级,用于确定进程线程的调度优先级。如果没有指定以下优先级标志,优先级类默认为NORMAL_PRIORITY_CLASS,除非创建过程的优先级为IDLE_PRIORITY_CLASS.在这种情况下,子进程的默认优先级类为IDLE_PRIORITY_CLASS.可以指定以下标志之一:

优先含义
HIGH_PRIORITY_CLASS表示执行必须立即执行以执行正确运行的时间关键任务的进程。高优先级类进程的线程抢占正常优先级或空闲优先级进程的线程。一个例子是Windows任务列表,无论操作系统上的负载如何,Windows任务列表在用户调用时都必须快速响应。使用高优先级类时要格外小心,因为高优先级的CPU绑定应用程序可以使用几乎所有可用的周期。
IDLE_PRIORITY_CLASS表示一个进程,其线程仅在系统空闲时运行,并被任何在较高优先级类中运行的进程的线程抢占。一个例子是屏幕保护程序。空闲优先级类由子进程继承。
NORMAL_PRIORITY_CLASS表示没有特殊调度需要的正常进程。
REALTIME_PRIORITY_CLASS表示具有最高可能优先级的进程。实时优先级进程的线程抢占所有其他进程的线程,包括执行重要任务的操作系统进程。例如,执行超过非常短的间隔的实时进程可能导致磁盘缓存不会刷新或导致鼠标无响应。

【// pointer to new environment block】

指向新进程的环境块。如果此参数为NULL,则新进程将使用调用进程的环境。

一个环境块由一个以null结尾的空端字符串的块组成。每个字符串的形式如下:

name=value

因为等号用作分隔符,所以不能在环境变量的名称中使用。

如果应用程序提供环境块,而不是为此参数传递NULL,则系统驱动器的当前目录信息不会自动传播到新进程。有关这种情况的讨论以及如何处理,请参阅以下备注部分。

环境块可以包含Unicode或ANSI字符。如果【// pointer to new environment block】指向的环境块包含Unicode字符,则将设置【dwCreationFlags】字段的CREATE_UNICODE_ENVIRONMENT标志。如果块包含ANSI字符,该标志将被清除。

请注意,ANSI环境块由两个零字节终止:一个用于最后一个字符串,另一个用于终止块。Unicode环境块由四个零字节终止:两个用于最后一个字符串,另外两个用于终止块。

【lpCurrentDirectory】

指向一个以null结尾的字符串,指定子进程的当前驱动器和目录。字符串必须是包含驱动器盘符的完整路径和文件名。如果此参数为NULL,则使用与调用进程相同的当前驱动器和目录创建新进程。此选项主要用于需要启动应用程序并指定其初始驱动器和工作目录的shell。

【lpStartupInfo】

指向STARTUPINFO结构,指定新进程的主窗口应如何显示。

【lpProcessInformation】

指向PROCESS_INFORMATION结构的接收关于新进程的标识信息。

返回值

如果函数成功,返回值不为零。

如果函数失败,返回值为零。要获取扩展错误信息,请调用GetLastError.

备注

CreateProcess功能用于运行新程序。WinExecLoadModule功能仍然可用,但它们已实现为CreateProcess的调用。

除了创建一个进程,CreateProcess还创建一个线程对象。该线程使用初始堆栈创建,其大小在指定程序的可执行文件的映像头中描述。线程在图像的入口点开始执行。

新进程和新的线程句柄都具有完整的访问权限。对于任一句柄,如果没有提供安全描述符,则可以在需要该类型的对象句柄的任何函数中使用句柄。当提供安全描述符时,在授予访问权限之前,对句柄的所有后续使用执行访问检查。如果访问检查拒绝访问,则请求进程不能使用句柄来访问线程。

该进程被分配一个32位进程标识符。该标识符有效,直到该过程终止。它可以用于标识进程,或在OpenProcess函数中指定以打开进程的句柄。该进程中的初始线程也被分配了一个32位线程标识符。该标识符在线程终止之前有效,可用于唯一标识系统中的线程。这些标识符在PROCESS_INFORMATION结构中返回。

【lpApplicationName】【lpCommandLine】字符串中指定应用程序名称时,应用程序名称是否包含文件扩展名无关紧要,但有一个例外:文件扩展名为基于MS-DOS或基于Windows的应用程序。 COM必须包含.COM扩展名。

调用线程可以使用WaitForInputIdle函数等待新进程完成初始化,并等待用户输入,而不输入挂起。这对于父进程和子进程之间的同步很有用,因为CreateProcess返回而不等待新进程完成其初始化。例如,在尝试查找与新进程关联的窗口之前,创建过程将使用WaitForInputIdle.

关闭进程的首选方法是使用ExitProcess函数,因为此函数通知附加到接近终止进程的所有动态链接库(DLL)。关闭进程的其他方法不通知附加的DLL。请注意,当线程调用ExitProcess时,进程的其他线程将被终止,无需执行任何附加代码(包括连接的DLL的线程终止代码)的机会。

ExitProcessExitThreadCreateThreadCreateRemoteThread,并且正在开始(作为CreateProcess的调用结果))的进程在进程之间彼此序列化。一次只能在地址空间中发生其中一个事件。这意味着以下限制:

*在进程启动和DLL初始化例程中,可以创建新的线程,但是直到进程的DLL初始化完成为止,才能开始执行。

一个进程中只有一个线程可以在一个DLL初始化或分离例程中。

* ExitProcess函数不会返回,直到其DLL初始化或分离例程中没有线程为止。

创建的进程保留在系统中,直到进程中的所有线程已终止,并且进程的所有句柄及其任何线程已通过调用CloseHandle关闭。必须通过调用CloseHandle关闭进程和主线程的句柄。如果不需要这些句柄,最好在创建进程后立即关闭它们。

当进程中的最后一个线程终止时,会发生以下事件:

*进程打开的所有对象隐式关闭。

*进程的终止状态(由GetExitCodeProcess返回)从其初始值STILL_ACTIVE更改为终止的最后一个线程的终止状态。

*主线程的线程对象设置为信号状态,满足等待对象的任何线程。

*进程对象设置为信号状态,满足正在等待对象的任何线程。

If the current directory on drive C is \MSVC\MFC, there is an environment variable called =C: whose value is C:\MSVC\MFC. As noted in the previous description of 【// pointer to new environment block】, such current directory information for a system's drives does not automatically propagate to a new process when the CreateProcess function's 【// pointer to new environment block】 parameter is non-NULL. An application must manually pass the current directory information to the new process. To do so, the application must explicitly create the =X environment variable strings, get them into alphabetical order (because Windows NT and Windows 95 use a sorted environment), and then put them into the environment block specified by 【// pointer to new environment block】. Typically, they will go at the front of the environment block, due to the previously mentioned environment block sorting.

获取驱动器X的当前目录变量的一种方法是调用GetFullPathName (“X:”,。.).这避免了应用程序不得不扫描环境块。如果返回的完整路径为X:\\,则不需要将该值作为环境数据传递,因为根目录是新进程的驱动器X的默认当前目录。

CreateProcess函数返回的句柄对进程对象具有PROCESS_ALL_ACCESS访问权限。

【lpcurrentDirectory】参数指定的当前目录是子进程的当前目录。【lpCommandLine】参数下项目2中指定的当前目录是父进程的当前目录。

Windows NT:当使用CREATE_NEW_PROCESS_GROUP创建进程时,代表新进程执行SetConsoleCtrlHandler(NULL,TRUE)的隐式调用;这意味着新进程已禁用CTRL + C。这使得好的shell可以自己处理CTRL + C,并有选择地将该信号传递给子进程。CTRL + BREAK不被禁用,可用于中断进程/进程组。

也可以看看

AllocConsole, CloseHandle, CreateRemoteThread, CreateThread, ExitProcess, ExitThread, GenerateConsoleCtrlEvent, GetCommandLine, GetEnvironmentStrings, GetExitCodeProcess, GetFullPathName, GetStartupInfo, GetSystemDirectory, GetWindowsDirectory, LoadModule, OpenProcess, PROCESS_INFORMATION, ResumeThread, SECURITY_ATTRIBUTES, SetConsoleCtrlHandler, SetErrorMode, STARTUPINFO, TerminateProcess, WaitForInputIdle, WaitForDebugEvent, WinExec