如果为可执行文件制定完整路径,系统会按指定路径寻找。

  以上情况在pszApplicationName为NULL时才发生。当然也可以在pszApplicationName传递可执行文件名称,此时必须指定扩展名,否则进程不会被创建。系统会按照此处指定的路径寻找,如没有指定完整路径,系统会假定文件位于当前目录。如找不到,函数调用失败。

  当pszApplicationName指定文件名,pszCommandLine参数中的内容也会作为新进程的命令行传给它。

  如:

    STARTUPINFO si={sizeof(si)};

 PROCESS_INFORMATION pi;

 TCHAR cmdLine[200]=TEXT("WORDPAD a.txt");

 CreateProcess(TEXT("C:\windows\system32\NOTEPAD.exe"),

 cmdLine,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);

  命令行是“WORDPAD a.txt”,记事本程序将询问:a.txt不存在是否创建a.txt文件。第一个参数WORDPAD应该是作为程序名称传入的。

  为了创建一个新的进程,系统必须创建一个进程内核对象和一个线程内核对象,由于这些都是内核对象,所以父进程必须将安全属性关联到这两个对象上。可以通过psaProcess和psaThread为进程和线程安全对象指定默认的安全描述符。可以都为它们指定NULL,使用默认的安全属性,也可以分配并初始化两个SECURITY_ATTRIBUTES结构,以便创建安全权限并将它们分配给进程和线程对象。

  fdwCreate参数影响新进程创建的方式。如:指定CREATE_SUSPENDEd标识让系统在创建新进程时挂起其主线程。这样父进程可以修改子进程地址空间的内存、更改主线程优先级或是将其添加到作业中。修改完后可以调用ResumeThread来允许子进程执行代码。传入0 表示创建进程后立即运行。多个标志位可以组合使用。

  pvEnvironment参数指定一块内存,包含新进程要使用的环境字符串。但多数情况下都是传入NULL,表示子进程要继承父进程使用的一组环境字符串。也可以使用GetEnvironmentStrings函数,此函数获取主调进程正在使用的环境字符串地址,当我们为pvEnvirtonment传入NULL时,CreateProcess是调用这个函数。不使用这块内存时应该使用FreeEnvironmentStrings函数。

  pszCurDir允许父进程设置子进程的当前驱动器和目录。如果为NULL,新进程的工作目录与父进程的一样。

  psiStartInfo参数指向一个STARTUPINFO结构。该结构包含很多成员。Windows在创建新进程的时候使用它们,但是大多数应用程序仅仅使用它们的默认值。因此我们要做的起码的工作是将此结构的所有成员都初始化为0,将cb成员设为此结构的大小,如:

  STARTUPINFO si={sizeof(si)};

  此时除cb成员外,其他成员均为0。不能仅仅si.cb=sizeof(si);因为此时其他成员的值都是垃圾数据。

  ppiProcInfo参数指向PROCESS_INFORMATION结构,CreateProcess在返回时会初始化这个结构。


Typedef struct _PROCESS_INFORMATION

{

   HANDLE hProcess;

   HANDLE hThread;

   HANDLE dwProcessId;

   HANDLE dwThreadId;

}PROCESS_INFORMATION;

  CreateProcess创建的进程和线程对象将通过它返回。创建时系统会为每个对象指定一个初始的使用计数1,CreateProcess返回时由于PROCESS_INFORMATION结构中再次引用了进程和线程内核对象 此时它们的使用计数都变为2。可以理解为进程和线程实例本身也占有一个计数。当它们结束运行时这个使用计数被递减1。

  此时如果系统要释放进程对象,1:进程必须终止,此时使用计数递减1。2:父进程必须调用CloseHandle,使用计数再次减去1。线程类似。

  因此为了使不再使用的内核对象能够得到释放,一定要在不使用时调用CloseHandle关闭对句柄的引用。所有对该句柄的引用都被关闭后,当进程或线程终止时它们关联度的内核对象才能够被释放。