WinExec, ShellExecute,CreateProcess的对比

三个SDK函数: WinExec, ShellExecute,CreateProcess能够实现调用其余程序的要求,其中以WinExec最为简单,ShellExecute比WinExec灵活一些,CreateProcess最为复杂。
    WinExec 两个参数,前一个指定路径,后一个指定显示方式。
    ShellExecute 能够指定工做目录,而且还能够寻找文件的关联直接打开不用加载与文件关联的应用程序,ShellExecute还能够打开网页,启动相应的邮件关联发送邮件等等。
    CreateProcess 一共有十个参数,不过大部分均可以用NULL代替,它能够指定进程的安全属性,继承信息,类的优先级等等。若是咱们要获得足够多的关于新的进程的信息,控制新的进程的细节属性,若要达到这些目的,咱们就须要使用CreateProcess函数了。
 
三个SDK函数( WinExec、ShellExec、CrateProcess )的语法:
 
WinExec
这个函数最简单,只有两个参数,原型以下:
 
      UINT WinExec(
      LPCSTR lpCmdLine,   // 命令路径
      UINT uCmdShow      // 显示方式
      );
使用方法以下:
WinExec("Notepad.exe", SW_SHOW);  // 打开记事本
WinExec("D://Program Files//Test//Test.exe",SW_SHOWMAXIMIZED); // 以最大化的方式打开Test.exe
须要注意的是若用 SW_SHOWMAXMIZED 方式去加载一个无最大化按钮的程序,譬如Neterm,Calc 等等,就不会出现正常的窗体,可是已经被加到任务列表里了。
 
ShellExecute
原型以下:
      HINSTANCE ShellExecute(
      HWND hwnd,           //父窗口句柄
      LPCTSTR lpOperation,   //操做, 打开方式 "edit","explore","open","find","print","NULL"
      LPCTSTR lpFile,         //文件名,前面可加路径
      LPCTSTR lpParameters,   //参数
      LPCTSTR lpDirectory,    //默认文件夹
      INT nShowCmd          //显示方式
);
使用方法以下:
ShellExecute(NULL,"open","C://Test.txt",NULL,NULL,SW_SHOWNORMAL); // 打开C:/Test.txt 文件
ShellExecute(NULL, "open", "http://www.google.com", NULL, NULL, SW_SHOWNORMAL); // 打开网页www.google.com
ShellExecute(NULL,"explore", "D://C ",NULL,NULL,SW_SHOWNORMAL); // 打开目录D:/C
ShellExecute(NULL,"print","C://Test.txt",NULL,NULL, SW_HIDE); // 打印文件C:/Test.txt
ShellExecute不支持定向输出。
 
CreateProcess
原型以下:
      BOOL CreateProcess(
      LPCTSTR lpApplicationName, //执行程序名
      LPTSTR lpCommandLine,  // 参数行
      //下面两个参数描述了所建立的进程和线程的安全属性,若是为NULL则使用默认的安全属性
      LPSECURITY_ATTRIBUTES lpProcessAttributes,  // process security attributes
      LPSECURITY_ATTRIBUTES lpThreadAttributes,   // thread security attributes
      BOOL bInheritHandles,  // 继承标志
      DWORD dwCreationFlags, // 建立标志
      LPVOID lpEnvironment,  // 环境变量
      LPCTSTR lpCurrentDirectory,   // 运行该进程的初始目录
      LPSTARTUPINFO lpStartupInfo,  // 用于在建立子进程时设置各类属性
      LPPROCESS_INFORMATION lpProcessInformation //用于在进程建立后接受相关信息
      );
使用方法以下:
             PROCESS_INFORMATION pi;
                       STARTUPINFO si;
                       memset(&si,0,sizeof(si));
                       si.cb=sizeof(si);
                      si.wShowWindow=SW_SHOW;
                       si.dwFlags=STARTF_USESHOWWINDOW;
                       bool fRet=CreateProcess("D://putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);
 
能够看出,经过上面的几个不一样的方法,均可以实如今应用程序中打开其余应用程序的目的,其中有些方法可能会麻烦一点,因此就须要咱们根据不一样的目的去选择最适合本身的方法去实现本身的目的!
 
 
关于三个SDK函数: WinExec, ShellExecute,CreateProcess的其余注意事项:
一、定义头文件
在头文件stdafx.h中必须定义如下两个头文件:
#include <shlobj.h> // 可替换为 windows.h
#include <shellapi.h>
若是定义了头文件 #include <windows.h>的话就没必要定义 #include <shlobj.h>了,"windows.h" 不光是包含了"shellapi.h",它还定义了许多数据类型,若是没有这些数据类型,shellapi.h自己会出错。
 
二、定义路径
C 中所表示的路径要用 " // "而不是日常所用的" / ",因此以上三个函数表示路径都为:
Disk://Directory//...//File name
WinExec("D://Program Files//Test//Test.exe",SW_SHOWMAXIMIZED);
ShellExecute(NULL,"open","C://Test.txt",NULL,NULL,SW_SHOWNORMAL);
bool fRet=CreateProcess("D://putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);
//--------------------------------------------------------------------------------------------------------
BOOL CreateProcess
 
  (
 
  LPCTSTRlpApplicationName,
 
  LPTSTRlpCommandLine,
 
  LPSECURITY_ATTRIBUTES lpProcessAttributes。
 
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
 
  BOOL bInheritHandles,
 
  DWORD dwCreationFlags,
 
  LPVOID lpEnvironment,
 
  LPCTSTR lpCurrentDirectory,
 
  LPSTARTUPINFO lpStartupInfo,
 
  LPPROCESS_INFORMATIONlpProcessInformation
 
  );
 
编辑本段参数
  1.lpApplicationName:
 
  指向一个NULL结尾的、用来指定可执行模块的字符串。
 
  这个字符串能够是可执行模块的绝对路径,也能够是相对路径,在后一种状况下,函数使用当前驱动器和目录创建可执行模块的路径。
 
  这个参数能够被设为NULL,在这种状况下,可执行模块的名字必须处于 lpCommandLine 参数的最前面并由空格符与后面的字符分开。
 
  这个被指定的模块能够是一个Win32应用程序。若是适当的子系统在当前计算机上可用的话,它也能够是其余类型的模块(如MS-DOS 或 OS/2)。
 
  在Windows NT中,若是可执行模块是一个16位的应用程序,那么这个参数应该被设置为NULL而且应该在lpCommandLine参数中指定可执行模块的名称。16位的应用程序是以DOS虚拟机或Win32上的Windows(WOW) 为进程的方式运行。
 
  2.lpCommandLine:
 
  指向一个以NULL结尾的字符串,该字符串指定要执行的命令行。
 
  这个参数能够为空,那么函数将使用lpApplicationName参数指定的字符串当作要运行的程序的命令行。
 
  若是lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数指定将被运行的模块的命令行。新运行的进程可使用GetCommandLine函数得到整个命令行。C语言程序可使用argc和argv参数。
 
  若是lpApplicationName参数为空,那么这个字符串中的第一个被空格分隔的要素指定可执行模块名。若是文件名不包含扩展名,那么.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或16位Windows为基础的应用程序,lpCommandLine参数应该是一个以可执行文件的文件名做为第一个要素的绝对路径,由于这样作可使32位Windows程序工做的很好,这样设置lpCommandLine参数是最强壮的。
 
  注意:Visual C++ 2005之后的版本中,若是向CreateProcess函数传递一个常量指针做为命令行参数的话,将会发生访问违规错误。缘由是系统在[1]执行该函数时会修改lpCommandLine所指向的字符串(好比解释转义字符等)。所以,在调用此函数前,应该定义一个临时字符数组变量来保存命令行参数,并将这个临时变量做为lpCommandLine参数传递.
 
  传递参数例子:
 
  LPTSTR szCmdline = _tcsdup(TEXT("c:\\test.bat"));//用szCmdline作CreateProcess第2参数,VS2008测试经过
 
  3.lpProcessAttributes:
 
  指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄能够被子进程继承。若是lpProcessAttributes参数为空(NULL),那么句柄不能被继承。
 
  在Windows NT中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了新进程的安全描述符,若是参数为空,新进程使用默认的安全描述符。
 
  在Windows95中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员被忽略。
 
  4.lpThreadAttributes:
 
  指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的指向线程的句柄能够被子进程继承。若是lpThreadAttributes参数为空(NULL),那么句柄不能被继承。
 
  在Windows NT中,SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了主线程的安全描述符,若是参数为空,主线程使用默认的安全描述符。
 
  在Windows95中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员被忽略。
 
  5.bInheritHandles:
 
  指示新进程是否从调用进程处继承了句柄。
 
  若是参数的值为真,调用进程中的每个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有彻底相同的值和访问权限。
 
  6.dwCreationFlags:
 
  指定附加的、用来控制优先类和进程的建立的标志。如下的建立标志能够以除下面列出的方式外的任何方式组合后指定。
 
  (1)值:CREATE_DEFAULT_ERROR_MODE
 
  含义:新的进程不继承调用进程的错误模式。CreateProcess函数赋予新进程当前的默认错误模式做为替代。应用程序能够调用SetErrorMode函数设置当前的默认错误模式。
 
  这个标志对于那些运行在没有硬件错误环境下的多线程外壳程序是十分有用的。
 
  对于CreateProcess函数,默认的行为是为新进程继承调用者的错误模式。设置这个标志以改变默认的处理方式。
 
  (2)值:CREATE_NEW_CONSOLE
 
  含义:新的进程将使用一个新的控制台,而不是继承父进程的控制台。这个标志不能与DETACHED_PROCESS标志一块儿使用。
 
  (3)值:CREATE_NEW_PROCESS_GROUP
 
  含义:新进程将使一个进程树的根进程。进程树中的所有进程都是根进程的子进程。新进程树的用户标识符与这个进程的标识符是相同的,由lpProcessInformation参数返回。进程树常用GenerateConsoleCtrlEvent函数容许发送CTRL+C或CTRL+BREAK信号到一组控制台进程。
 
  (4)值:CREATE_SEPARATE_WOW_VDM
 
  含义:(只适用于Windows NT)这个标志只有当运行一个16位的Windows应用程序时才是有效的。若是被设置,新进程将会在一个私有的虚拟DOS机(VDM)中运行。另外,默认状况下全部的16位Windows应用程序都会在同一个共享的VDM中以线程的方式运行。单独运行一个16位程序的优势是一个应用程序的崩溃只会结束这一个VDM的运行;其余那些在不一样VDM中运行的程序会继续正常的运行。一样的,在不一样VDM中运行的16位Windows应用程序拥有不一样的输入队列,这意味着若是一个程序暂时失去响应,在独立的VDM中的应用程序可以继续得到输入。
 
  (5)值:CREATE_SHARED_WOW_VDM
 
  含义:(只适用于Windows NT)这个标志只有当运行一个16位的Windows应用程序时才是有效的。若是WIN.INI中的Windows段的DefaultSeparateVDM选项被设置为真,这个标识使得CreateProcess函数越过这个选项并在共享的虚拟DOS机中运行新进程。
 
  (6)值:CREATE_SUSPENDED
 
  含义:新进程的主线程会以暂停的状态被建立,直到调用ResumeThread函数被调用时才运行。
 
  (7)值:CREATE_UNICODE_ENⅥRONMENT
 
  含义:若是被设置,由lpEnvironment参数指定的环境块使用Unicode字符,若是为空,环境块使用ANSI字符。
 
  (8)值:DEBUG_PROCESS
 
  含义:若是这个标志被设置,调用进程将被当作一个调试程序,而且新进程会被当作被调试的进程。系统把被调试程序发生的全部调试事件通知给调试器。
 
  若是你使用这个标志建立进程,只有调用进程(调用CreateProcess函数的进程)能够调用WaitForDebugEvent函数。
 
  (9)值:DEBUG_ONLY_THIS_PROCESS
 
  含义:若是此标志没有被设置且调用进程正在被调试,新进程将成为调试调用进程的调试器的另外一个调试对象。若是调用进程没有被调试,有关调试的行为就不会产生。
 
  (10)值:DETACHED_PROCESS
 
  含义:对于控制台进程,新进程没有访问父进程控制台的权限。新进程能够经过AllocConsole函数本身建立一个新的控制台。这个标志不能够与CREATE_NEW_CONSOLE标志一块儿使用。
 
  dwCreationFlags参数
 
  还用来控制新进程的优先类,优先类用来决定此进程的线程调度的优先级。若是下面的优先级类标志都没有被指定,那么默认的优先类是NORMAL_PRIORITY_CLASS,除非被建立的进程是IDLE_PRIORITY_CLASS。在这种状况下子进程的默认优先类是IDLE_PRIORITY_CLASS。
 
  能够下面的标志中的一个:
 
  优先级:HIGH_PRIORITY_CLASS
 
  含义:指示这个进程将执行时间临界的任务,因此它必须被当即运行以保证正确。这个优先级的程序优先于正常优先级或空闲优先级的程序。一个例子是Windows任务列表,为了保证当用户调用时能够马上响应,放弃了对系统负荷的考虑。确保在使用高优先级时应该足够谨慎,由于一个高优先级的CPU关联应用程序能够占用几乎所有的CPU可用时间。
 
  优先级:IDLE_PRIORITY_CLASS
 
  含义:指示这个进程的线程只有在系统空闲时才会运行而且能够被任何高优先级的任务打断。例如屏幕保护程序。空闲优先级会被子进程继承。
 
  优先级:NORMAL_PRIORITY_CLASS
 
  含义:指示这个进程没有特殊的任务调度要求。
 
  优先级:REALTIME_PRIORITY_CLASS
 
  含义:指示这个进程拥有可用的最高优先级。一个拥有实时优先级的进程的线程能够打断全部其余进程线程的执行,包括正在执行重要任务的系统进程。例如,一个执行时间稍长一点的实时进程可能致使磁盘缓存不足或鼠标反映迟钝。
 
  7.lpEnvironment:
 
  指向一个新进程的环境块。若是此参数为空,新进程使用调用进程的环境。
 
  一个环境块存在于一个由以NULL结尾的字符串组成的块中,这个块也是以NULL结尾的。每一个字符串都是name=value的形式。
 
  由于相等标志被当作分隔符,因此它不能被环境变量当作变量名。
 
  与其使用应用程序提供的环境块,不如直接把这个参数设为空,系统驱动器上的当前目录信息不会被自动传递给新建立的进程。对于这个状况的探讨和如何处理,请参见注释一节。
 
  环境块能够包含Unicode或ANSI字符。若是lpEnvironment指向的环境块包含Unicode字符,那么dwCreationFlags字段的CREATE_UNICODE_ENⅥRONMENT标志将被设置。若是块包含ANSI字符,该标志将被清空。
 
  请注意一个ANSI环境块是由两个零字节结束的:一个是字符串的结尾,另外一个用来结束这个快。一个Unicode环境块是由四个零字节结束的:两个表明字符串结束,另两个用来结束块。
 
  8.lpCurrentDirectory:
 
  指向一个以NULL结尾的字符串,这个字符串用来指定子进程的工做路径。这个字符串必须是一个包含驱动器名的绝对路径。若是这个参数为空,新进程将使用与调用进程相同的驱动器和目录。这个选项是一个须要启动应用程序并指定它们的驱动器和工做目录的外壳程序的主要条件。
 
  9.lpStartupInfo:
 
  指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。
 
  10.lpProcessInformation:
 
  指向一个用来接收新进程的识别信息的PROCESS_INFORMATION结构体。
 
编辑本段返回值
  若是函数执行成功,返回非零值。
 
  若是函数执行失败,返回零,可使用GetLastError函数得到错误的附加信息。
 
  注释:
 
  CreateProcess函数用来运行一个新程序。WinExec和LoadModule函数依旧可用,可是它们一样经过调用CreateProcess函数实现。
 
  另外CreateProcess函数除了建立一个进程,还建立一个线程对象。这个线程将连同一个已初始化了的堆栈一块儿被建立,堆栈的大小由可执行文件的文件头中的描述决定。线程由文件头处开始执行。
 
  新进程和新线程的句柄被以全局访问权限建立。对于这两个句柄中的任一个,若是没有安全描述符,那么这个句柄就能够在任何须要句柄类型做为参数的函数中被使用。当提供安全描述符时,在接下来的时候当句柄被使用时,老是会先进行访问权限的检查,若是访问权限检查拒绝访问,请求的进程将不能使用这个句柄访问这个进程。
 
  这个进程会被分配给一个32位的进程标识符。直到进程停止这个标识符都是有效的。它能够被用来标识这个进程,或在OpenProcess函数中被指定以打开这个进程的句柄。进程中被初始化了的线程同样会被分配一个32位的线程标识符。这个标识符直到线程停止都是有效的且能够用来在系统中惟一标识这个线程。这些标识符在PROCESS_INFORMATION结构体中返回。
 
  当在lpApplicationName或lpCommandLine参数中指定应用程序名时,应用程序名中是否包含扩展名都不会影响运行,只有一种状况例外:一个以.com为扩展名的MS-DOS程序或Windows程序必须包含.com扩展名。
 
  调用进程能够经过WaitForInputIdle函数来等待新进程完成它的初始化并等待用户输入。这对于父进程和子进程之间的同步是极其有用的,由于CreateProcess函数不会等待新进程完成它的初始化工做。举例来讲,在试图与新进程关联的窗口以前,进程应该先调用WaitForInputIdle。
 
  首选的结束一个进程的方式是调用ExitProcess函数,由于这个函数通知这个进程的全部动态连接库(DLLs)程序已进入结束状态。其余的结束进程的方法不会通知关联的动态连接库。注意当一个进程调用ExitProcess时,这个进程的其余线程没有机会运行其余任何代码(包括关联动态连接库的终止代码)。
 
  ExitProcess,ExitThread,CreateThread,CreateRemoteThread,当一个进程启动时(调用了CreateProcess的结果)是在进程中序列化进行的。在一段地址空间中,同一时间内这些事件中只有一个能够发生。这意味着下面的限制将保留:
 
  *在进程启动和DLL初始化阶段,新的线程能够被建立,可是直到进程的DLL初始化完成前它们都不能开始运行。
 
  *在DLL初始化或卸下例程中进程中只能有一个线程。
 
  *直到全部的线程都完成DLL初始化或卸下后,ExitProcess函数才返回。
 
  在进程中的全部线程都终止且进程全部的句柄和它们的线程被经过调用CloseHandle函数终止前,进程会留在系统中。进程和主线程的句柄都必须经过调用CloseHandle函数关闭。若是再也不须要这些句柄,最好在建立进程后马上关闭它们。
 
  当进程中最后一个线程终止时,下列的事件发生:
 
  *全部由进程打开的对象都会关闭。
 
  *进程的终止状态(由GetExitCodeProcess函数返回)从它的初始值STILL_ACTⅣE变为最后一个结束的线程的结束状态。
 
  *主线程的线程对象被设置为标志状态,供其余等待这个对象的线程使用。
 
  *进程对象被设置为标志状态,供其余等待这个对象的线程使用。
 
  假设当前在C盘上的目录是\MSVC\MFC且有一个环境变量叫作C:,它的值是C:\MSVC\MFC,就像前面lpEnvironment中提到过的那样,这样的系统驱动器上的目录信息在CreateProcess函数的lpEnvironment参数不为空时不会被自动传递到新进程里。一个应用程序必须手动地把当前目录信息传递到新的进程中。为了这样作,应用程序必须直接建立环境字符串,并把它们按字母顺序排列(由于Windows NT和Windows 95使用一种简略的环境变量),并把它们放进lpEnvironment中指定的环境块中。相似的,他们要找到环境块的开头,又要重复一次前面提到的环境块的排序。
 
  一种得到驱动器X的当前目录变量的方法是调用GetFullPathName("x:",..)。这避免了一个应用程序必须去扫描环境块。若是返回的绝对路径是X:\,就不须要把这个值看成一个环境数据去传递了,由于根目录是驱动器X上的新进程的默认当前目录。
 
  由CreateProcess函数返回的句柄对于进程对象具备PROCESS_ALL_ACCESS的访问权限。
 
  由lpcurrentDirectory参数指定的当前目录室子进程对象的当前目录。lpCommandLine参数指定的第二个项目是父进程的当前目录。
 
  对于Windows NT,当一个进程在指定了CREATE_NEW_PROCESS_GROUP的状况下被建立时,一个对于SetConsoleCtrlHandler(NULL,True)的调用被用在新的进程上,这意味着对新进程来讲CTRL+C是无效的。这使得上层的外科程序能够本身处理CTRL+C信息并有选择的把这些信号传递给子进程。CTRL+BREAK依旧有效,并可被用来中断进程/进程树的执行。
 
  安全注释:
 
  第一个参数lpApplicationName多是空,这种状况下,可执行文件的名字必须在lpCommandLine中,lpCommandLine参数中能够包含空格。若是可执行文件或路径中包含空格,那么就会有执行不正确文件的风险,这是因为这个函数解析空格的方法引发的。例如:下边这个例子就很危险,由于它试图运行Program.exe文件,若是这个文件存在,它就会代替MyApp.exe文件的运行。
 
  CreateProcess(NULL,”C:\\Program Files\\MyApp.exe”,…….)
 
  若是有恶意的用户在系统编写了一个名为Program.exe的文件,那么任何调用CreateProcess函数,且在文件路径中使用Program Files文件夹的参数,都有可能会运行Program.exe文件,而不是运行原本打算运行的文件。
 
  要避免这个问题,能够不要将NULL值传递给lpApplicationName参数,或者在lpCommandLine中使用双引号(转义符)括起可执行文件的全路径名,以下所示:
 
  CreateProcess(NULL,”\”C:\\Program Files\\MyApp.exe\” -L -S”,…….)
 
  -L和-S是MyApp.exe可执行文件的参数。
 
  最后要说明的一点是:在lpApplicationName中的参数和lpCommandLine中的第一个参数是同样的,有人说显得有些重复,其实这样作纯粹是一种被公认化了习惯!
 
  参见
 
  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
 
  快捷信息:
 
  导入库:kernel32.lib
 
  头文件:Winbase.h
 
编辑本段举例说明
C代码
  #include <stdio.h>
 
  #include <windows.h>
 
  int main(int argc,char *argv[])
 
  {
 
  char szCommandLine[] = "notepad";
 
  STARTUPINFO si = { sizeof(si) };
 
  PROCESS_INFORMATION pi;
 
  si.dwFlags = STARTF_USESHOWWINDOW; // 指定wShowWindow成员有效
 
  si.wShowWindow = TRUE; // 此成员设为TRUE的话则显示新建进程的主窗口
 
  BOOL bRet = CreateProcess (
 
  NULL,// 不在此指定可执行文件的文件名
 
  szCommandLine,// 命令行参数
 
  NULL,// 默认进程安全性
 
  NULL,// 默认进程安全性
 
  FALSE,// 指定当前进程内句柄不能够被子进程继承
 
  CREATE_NEW_CONSOLE,// 为新进程建立一个新的控制台窗口
 
  NULL,// 使用本进程的环境变量
 
  NULL,// 使用本进程的驱动器和目录
 
  &si,
 
  &pi) ;
 
  if(bRet)
 
  {
 
  // 不使用的句柄最好关掉
 
  CloseHandle(pi.hThread);
 
  CloseHandle(pi.hProcess);
 
  printf("新进程的ID号:%d\n",pi.dwProcessId);
 
  printf("新进程的主线程ID号:%d\n",pi.dwThreadId);
 
  }
 
  return 0;
 
  }
C++代码
  #include <iostream>
 
  #include<windows.h>
 
  using namespace std;
 
  int main()
 
  {
 
  STARTUPINFO si; //一些必备参数设置
 
  memset(&si,0,sizeof(STARTUPINFO));
 
  si.cb = sizeof(STARTUPINFO);
 
  si.dwFlags = STARTF_USESHOWWINDOW;
 
  si.wShowWindow = SW_SHOW;
 
  PROCESS_INFORMATION pi; //必备参数设置结束
 
  if(!CreateProcess("c:\\windows\\system32\\notepad.exe",NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
 
  {
 
  cout<<"Create Fail!"<<endl;
 
  exit(1);
 
  }
 
  else
 
  {
 
  cout<<"Success!"<<endl;
 
  }
 
  return 0;
 
  }ios

相关文章
相关标签/搜索