多线程里可否使用WinExec或createprocess failed来执行程序?

8539人阅读
一、三个SDK函数:&
WinExec,ShellExecute ,CreateProcess可以实现调用其他程序的要求,其中以WinExec最为简单,ShellExecute比WinExec灵活一些,CreateProcess最为复杂。
WinExec 两个参数,前一个指定路径,后一个指定显示方式。
ShellExecute 可以指定工作目录,并且还可以寻找文件的关联直接打开不用加载与文件关联的应用程序,ShellExecute还可以打开网页,启动相应的邮件关联发送邮件等等。
CreateProcess 一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等。如果我们要得到足够多的关于新的进程的信息,控制新的进程的细节属性,若要达到这些目的,我们就需要使用CreateProcess函数了。
1.winexec(String&lpCmdLine,Long&nCmdShow);
类型及说明
String,包含要执行的命令行
Long,为窗口指定可视性方面的一个命令。请用下述任何一个常数
隐藏窗口,活动状态给令一个窗口
SW_MINIMIZE
最小化窗口,活动状态给令一个窗口
SW_RESTORE
用原来的大小和位置显示一个窗口,同时令其进入活动状态
用当前的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOWMAXIMIZED
最大化窗口,并将其激活
SW_SHOWMINIMIZED
最小化窗口,并将其激活
SW_SHOWMINNOACTIVE
最小化一个窗口,同时不改变活动窗口
用当前的大小和位置显示一个窗口,不改变活动窗口
SW_SHOWNOACTIVATE
用最近的大小和位置显示一个窗口,同时不改变活动窗口
SW_SHOWNORMAL
与SW_RESTORE相同
例:&winexec(&c:\\a.txt&,SW_SHOW);
2.ShellExecute
类型及说明
Long,指定一个窗口的句柄,有时候,windows程序有必要在创建自己的主窗口前显示一个消息框
lpOperation
String,指定字串“open”来打开lpFlie文档,或指定“Print”来打印它
String,想用关联程序打印或打开一个程序名或文件名
lpParameters
String,如lpszFlie是可执行文件,则这个字串包含传递给执行程序的参数
lpDirectory
String,想使用的完整路径
Long,定义了如何显示启动程序的常数值。参考上表.
使用方法如下:
例:ShellExecute(Handle, ''open'', PChar(''c:\test\readme.txt''), nil, nil, SW_SHOW);
ShellExecute(NULL,&open&,&C://Test.txt&,NULL,NULL,SW_SHOWNORMAL); // 打开C:/Test.txt 文件
ShellExecute(NULL, &open&, &&,/ NULL, NULL, SW_SHOWNORMAL); // 打开网页
ShellExecute(NULL,&explore&, &D://C++&,NULL,NULL,SW_SHOWNORMAL); // 打开目录D:/C++
ShellExecute(NULL,&print&,&C://Test.txt&,NULL,NULL, SW_HIDE); // 打印文件C:/Test.txt
类型及说明
lpApplicationName
String,要执行的应用程序的名字。可设为vbNullString;在这种情况下,应用程序的名字应在lpCommandLine参数的起始处出现
lpCommandLine
String,要执行的命令行。可用GetCommandLine函数取得一个进程使用的命令行。Windows会尽可能地根据下述搜索顺序来查找执行文件:
(1)包含了父进程执行文件的目录
(2)父进程当前的目录
(3)由返回的系统目录
(4)仅适于windows NT:16位系统目录
(5)由返回的Windows目录
(6)由PATH环境变量指定的目录
lpProcessAttributes
SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值)----表示采用不允许继承的默认描述符。该参数定义了进程的安全特性
lpThreadAttributes
SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值)----表示采用不允许继承的默认描述符。该参数定义了进程之主线程的安全特性
bInheritHandles
Long,TRUE表示允许当前进程中的所有句柄都由新建的子进程继承
dwCreationFlags
Long,来自API32.TXT文件的一个或多个下述常数之一,它们都带有前缀CREATE_。下面这些用于VB程序员:
CREATE_SEPARATE_WOW_VDM(仅适用于NT)
启动一个16位的Windows应用程序时,强迫它在自己的内存空间运行
CREATE_SHARED_WOW_VDM(仅适用于NT)
启动一个16位的Windows应用程序时,强迫它在共享的16位虚拟机(VM)内运行
CREATE_SUSPENDED
立即挂起新进程。除非调用了ResumeThread函数函数,否则它不会恢复运行
也可能是下述常数之一,用于指定优先级
IDLE_PRIORITY_CLASS
新进程应该有非常低的优先级----只有在系统空闲的时候才能运行。基本值是4
HIGH_PRIORITY_CLASS
新进程有非常高的优先级,它优先于大多数应用程序。基本值是13。注意尽量避免采用这个优先级
NORMAL_PRIORITY_CLASS
标准优先级。如进程位于前台,则基本值是9;如在后台,则优先值是7
不要在VB中使用REALTIME_PRIORITY_CLASS
lpEnvironment
Any,指向一个环境块的指针(环境缓冲区的头一个字符,或者环境块的地址)
lpCurrentDriectory
String,新进程的当前目录路径。调用函数的时候,可用vbNullString指定当前目录
lpStartupInfo
STARTUPINFO,指定一个STARTUPINFO结构,其中包含了创建进程时使用的附加信息
lpProcessInformation
PROCESS_INFORMATION,该结构用于容纳新进程的进程和线程标识符。大多数情况下,一旦这个函数返回,父应用程序都会关闭两个句柄。
---------------------------------------------------------------------------------------------------------
有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。CreateProcess因为使用复杂,比较少用。
  WinExec主要运行EXE文件。
  ⑴ 函数原型: UINT Win Exec(LPCSTR lpCmdLine, UINT uCmdShow);
  ⑵ 参数:
  lpCmdLine:指向一个空结束的字符串,串中包含将要执行的应用程序的命令行(文件名加上可选参数)。
  uCmdShow:定义Windows应用程序的窗口如何显示,并为CreateProcess函数提供STARTUPINFO参数的wShowWindow成员的值。
  ⑶ 返回值:
  若函数调用成功,则返回值大于31。若函数调用失败,则返回值为下列之一:
  ① 0:系统内存或资源已耗尽。
  ② ERROR_BAD_FORMAT:EXE文件无效(非Win32.EXE或.EXE影像错误)。
  ③ ERROR_FILE_NOT_FOUND:指定的文件未找到。
  ④ ERROR_PATH_NOT_FOUND:指定的路径未找到。
  虽然Microsoft认为WinExec已过时,但是在许多时候,简单的WinExec函数仍是运行新程序的最好方式。简单地传送作为第一个参数的 命令行,还需要决定如何显示程序(该程序也许会忽视它)的第二个参数。通常,将其设置为SW_SHOW,也可尝试SW_MINIMIZED或 SW_MAXIMIZED。WinExec不允许用CreateProcess获得的所有选项,而它的确简单。
  ShellExecute不仅可以运行EXE文件,也可以运行已经关联的文件。
1、标准用法
  ShellExecute函数原型及参数含义如下:
HINSTANCE ShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd);
  ●hWnd:用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。例如,可以将其设置为应用程序主窗口句柄,即Application.Handle,也可以将其设置为桌面窗口句柄(用GetDesktopWindow函数获得)。
  ●lpOperation:用于指定要进行的操作。其中“open”操作表示执行由FileName参数指定的程序,或打开由FileName参数指定的文件或文件夹;“print”操作表示打印由FileName参数指定的文件;“explore”操作表示浏览由FileName参数指定的文件夹。当参数设为nil时,表示执行默认操作“open”。
  ●lpFileName:用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。
  ●lpParameters:若FileName参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为nil或PChar(0)。
  ●lpDirectory:用于指定默认目录。
  ●lpShowCmd:若FileName参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。
  返回值:
#include &stdio.h&
#include &stdlib.h&
#include &windows.h&
#include &shellapi.h&
int main( void )
HINSTANCE hNewExe = ShellExecuteA(NULL, &open&, &d:\\tese.log&, NULL, NULL, SW_SHOW);
if ((DWORD)hNewExe &= 32)
printf(&return value:%d\n&, (DWORD)hNewExe);
printf(&successed!\n&);
   printf(&GetLastError: %d\n&, GetLastError());
system(&pause&);
 当“D:\\test.log”文件不存在是,执行结果如下:
  这里若函数执行错误, GetLastError()不一定能捕获到错误代码,例如当“d:\\tese.log”文件存在,将记事本¬epad.exe&命名为其他名字时:
  另外两个函数的返回值就不列出了。
2、特殊用法
  1)如果将FileName参数设置为“http:”协议格式,那么该函数将打开默认浏览器并链接到指定的URL地址。若用户机器中***了多个浏览器,则该函数将根据Windows 9x/NT注册表中http协议处理程序(Protocols Handler)的设置确定启动哪个浏览器。
  格式一:http://网站域名。       如:ShellExecute(handle, “open”, “http://www.”, nil, nil, SW_SHOWNORMAL);
  格式二:http://网站域名/网页文件名。  如:ShellExecute(handle, “open”, “http://www./default.htm”, nil, nil, SW_SHOWNORMAL);
  2)如果将FileName参数设置为“mailto:”协议格式,那么该函数将启动默认邮件客户程序,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若用户机器中***了多个邮件客户程序,则该函数将根据Windows 9x/NT注册表中mailto协议处理程序的设置确定启动哪个邮件客户程序。
  格式一:mailto:     如:ShellExecute(handle, &open&, &mailto:&, nil, nil, SW_SHOWNORMAL);打开新邮件窗口。
  格式二:mailto:用户账号@邮件服务器地址 如:ShellExecute(handle, &open&, &mailto:who@mail.&, nil, nil, SW_SHOWNORMAL);
  打开新邮件窗口,并自动填入收件人地址。若指定多个收件人地址,则收件人地址之间必须用分号或逗号分隔开(下同)
如:ShellExecute(this-&m_hWnd, &open&, &mailto:&, &&, &&, SW_SHOW);
  格式三:mailto:用户账号@邮件服务器地址?subject=邮件主题&body=邮件正文
  如:ShellExecute(handle, &open&, &mailto:who@mail.?subject=Hello&Body=This is a test&, nil, nil, SW_SHOWNORMAL);
  打开新邮件窗口,并自动填入收件人地址、邮件主题和邮件正文。若邮件正文包括多行文本,则必须在每行文本之间加入换行转义字符%0a。
例子(delphi):
在一个应用程序调用c:Project1.
  ShellExecute(handle, ’open’,’c:Project1.exe’,’字串内容’,nil, SW_SHOWNORMAL);
在Project1.exe里可以调用:
procedure TForm1.FormCreate(Sender: TObject);
for i:=1 to paramcount do
if ParamStr(i)〈〉’’ then showmessage(ParamStr(i));
最后的那个参数,为窗口指定可视性方面的一个命令。 请用下述任何一个常数
SW_HIDE 隐藏窗口,活动状态给令一个窗口
SW_MINIMIZE 最小化窗口,活动状态给令一个窗口
SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOWMAXIMIZED 最大化窗口,并将其激活
SW_SHOWMINIMIZED 最小化窗口,并将其激活
SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口
SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口
SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口
SW_SHOWNORMAL 与SW_RESTORE相同
  3、深入浅出ShellExecute 译者:徐景周(原作:Nishant S)
Q: 如何打开一个应用程序? 正如您所看到的,我并没有传递程序的完整路径。
  ShellExecute(this-&m_hWnd, &open&, &calc.exe&, &&, &&, SW_SHOW);
或ShellExecute(this-&m_hWnd, &open&, ¬epad.exe&, &c:\\MyLog.log&, &&, SW_SHOW);
Q: 如何打开一个同系统程序相关连的文档?
ShellExecute(this-&m_hWnd, &open&, &c:\\abc.txt&, &&, &&, SW_SHOW);
Q: 如何打开一个网页?
ShellExecute(this-&m_hWnd, &open&, &&, &&, &&, SW_SHOW);
Q: 如何激活相关程序,发送EMAIL?
ShellExecute(this-&m_hWnd,&open&, &mailto:&,&&,&&, SW_SHOW );
Q: 如何用系统打印机打印文档?
ShellExecute(this-&m_hWnd, &print&, &c:\\abc.txt&, &&, &&, SW_HIDE);
Q: 如何用系统查找功能来查找指定文件?
ShellExecute(m_hWnd, &find&, &d:\\nish&, NULL, NULL, SW_SHOW);
Q: 如何启动一个程序,直到它运行结束?
    SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = &c:\\MyProgram.exe&;
ShExecInfo.lpParameters = &&;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
PROCESS_INFORMATION ProcessI
STARTUPINFO StartupI //This is an [in] parameter
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo); //Only compulsory field
if(CreateProcess(&c:\\winnt\\notepad.exe&, NULL, NULL,NULL,FALSE,0,NULL, NULL,&StartupInfo,&ProcessInfo))
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
MessageBox(&The process could not be started...&);
  Q: 如何显示文件或文件夹的属性?
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = &properties&;
ShExecInfo.lpFile = &c:\\&; //can be a file as well
ShExecInfo.lpParameters = &&;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
使用CreateProcess命令
  ⑴ 函数原型:
BOOL CreateProcess(
 LPCTSTR lpApplicationName,
 LPTSTR lpCommandLine,
 LPSECURITY_ATTRIBUTES lpProcessAttributes,
 LPSECURITY_ATTRIBUTES lpThreadAttributes,
 BOOL bInheritHandles,
 DWORD dwCreationFlags,
 LPVOID lpEnvironment,
 LPCTSTR lpCurrentDirectory,
 LPSTARTUPINFO lpStartupInfo,
 LPPROCESS_INFORMATION lpProcessInformation
  ⑵ 参数:
  lpApplicationName:指向一个以空结尾的串,他指定了要执行的模块
  lpCommandLine:指向一个以空结尾的串,该串定义了要执行的命令行。
  lpProcessAttributes:指向一个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子进程继承。
  lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子进程继承。
  bInheritHandles,:表明新进程是否从调用进程继承句柄。
  dwCreationFlags:定义控制优先类和进程创建的附加标志。
  lpEnvironment:指向一个新进程的环境块。
  lpCurrentDirectory:指向一个以空结尾的串,该串定义了子进程的当前驱动器和当前目录。
  lpStartupInfo:指向一个STARTUPINFO结构,该结构定义了新进程的主窗口将如何显示。
  lpProcessInformation:指向PROCESS_INFORMATION结构,该结构接受关于新进程的表示信息。
  ⑶ 返回值:
  若函数调用成功,则返回值不为0;若函数调用失败,返回值为0。
  在上述参数中,参数lpStartupInfo是STARTUPINFO结构。可以用来设置控台的标题,新窗口的的初始大小和位置,及重定向标准输入 和输出。新程序通常可以忽略多数这些数据项,如果选择那样做的话。可以规定该结构体中的标志,已表明要设置的数据段。有时,不想设置任何信息,也必须传递 一个有效的指针给空结构(确定设置大小到cb,及设置dwFlags成员为0)。参数lpProcessInformation返回进程和线程句柄,还包 括进程和线程ID。这些句柄拥有在参数lpProcessAttributes和lpThreadAttributes中规定的访问。
  要注意,针对CreateProcess的一些参数对控制台应用程序是特定的,而其它参数则对各种应用程序有用。大多数情况下,并不一定要填入 STARTUPINFO结构,但无论如何必须提供它。其返回值是布尔型的,而真正感兴趣的返回值发生于作为参数传送的结构中 (PROCESS_INFORMATION)。CreateProcess返回该结构中的进程ID及其句柄,以及初始线程ID及其句柄。可以将ID发送到 其它进程,或使用句柄来控制新进程。
  ShellExecute和WinExec命令用于简单的作业。如果要完全控制一个新进程,就必须调用CreateProcess。
---------------------------------------------------------------------------------------------------------
三、注意事项
1、定义头文件
在头文件stdafx.h中必须定义以下两个头文件:
#include &shlobj.h& // 可替换为 windows.h
#include &shellapi.h&
如果定义了头文件 #include &windows.h&的话就不必定义 #include &shlobj.h&了,&windows.h& 不光是包含了&shellapi.h&,它还定义了许多数据类型,如果没有这些数据类型,shellapi.h本身会出错。
2 ShellExecute是异步执行的,也就是说,不管执行的程序是否成功运行,运行的时间是长是短,ShellExecute函数都会立即返回
3可以使用system()来运行cmd命令
4可以用ShellExecute 和 批处理完成同步执行。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:789587次
积分:7878
积分:7878
排名:第1777名
原创:87篇
转载:159篇
评论:208条
阅读:11940
阅读:31648
(2)(4)(2)(3)(2)(1)(1)(5)(1)(1)(2)(6)(10)(10)(3)(1)(1)(1)(8)(1)(4)(6)(1)(12)(9)(1)(20)(4)(4)(4)(1)(3)(19)(8)(1)(1)(4)(2)(8)(9)(1)(1)(8)(11)(8)(5)(7)(6)(1)createprocess调用其他程序运行某程序时需要调用其他程序。而需被调动程序不存在。以下引自互联网:CreateProcess说明:WIN32API函数CreateProcess用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件。函数原型:BOOLCreateProcess(LPCTSTRlpApplicationName,LPTSTRlpCommandLine,LPSECURITY_ATTRIBUTESlpProcessAttributes。LPSECURITY_ATTRIBUTESlpThreadAttributes,BOOLbInheritHandles,DWORDdwCreationFlags,LPVOIDlpEnvironment,LPCTSTRlpCurrentDirectory,LPSTARTUPINFOlpStartupInfo,LPPROCESS_INFORMATIONlpProcessInformation);参数:lpApplicationName:指向一个NULL结尾的、用来指定可执行模块的字符串。这个字符串可以使可执行模块的绝对路径,也可以是相对路径,在后一种情况下,函数使用当前驱动器和目录建立可执行模块的路径。这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于lpCommandLine参数的最前面并由空格符与后面的字符分开。这个被指定的模块可以是一个Win32应用程序。如果适当的子系统在当前计算机上可用的话,它也可以是其他类型的模块(如MS-DOS或OS/2)。在WindowsNT中,如果可执行模块是一个16位的应用程序,那么这个参数应该被设置为NULL并且因该在lpCommandLine参数中指定可执行模块的名称。16位的应用程序是以DOS虚拟机或Win32上的Windows(WOW)为进程的方式运行。lpCommandLine:指向一个NULL结尾的、用来指定要运行的命令行。这个参数可以为空,那么函数将使用参数指定的字符串当作要运行的程序的命令行。如果lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数指定将被运行的模块的命令行。新运行的进程可以使用GetCommandLine函数获得整个命令行。C语言程序可以使用argc和argv参数。如果lpApplicationName参数为空,那么这个字符串中的第一个被空格分隔的要素指定可执行模块名。如果文件名不包含扩展名,那么.exe将被假定为默认的扩展名。如果文件名以一个点(.)结尾且没有扩展名,或文件名中包含路径,.exe将不会被加到后面。如果文件名中不包含路径,Windows将按照如下顺序寻找这个可执行文件:1.当前应用程序的目录。2.父进程的目录。3.Windows95:Windows系统目录,可以使用GetSystemDirectory函数获得。WindowsNT:32位Windows系统目录。可以使用GetSystemDirectory函数获得,目录名是SYSTEM32。4.在WindowsNT中:16位Windows系统目录。不可以使用Win32函数获得这个目录,但是它会被搜索,目录名是SYSTEM。5.Windows目录。可以使用GetWindowsDirectory函数获得这个目录。6.列在PATH环境变量中的目录。如果被创建的进程是一个以MS-DOS或16位Windows为基础的应用程序,lpCommandLine参数应该是一个以可执行文件的文件名作为第一个要素的绝对路径,因为这样做可以使32位Windows程序工作的很好,这样设置lpCommandLine参数是最强壮的。lpProcessAttributes:指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。在WindowsNT中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了新进程的安全描述符,如果参数为空,新进程使用默认的安全描述符。在Windows95中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员被忽略。lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。如果lpThreadAttributes参数为空(NULL),那么句柄不能被继承。在WindowsNT中,SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了主线程的安全描述符,如果参数为空,主线程使用默认的安全描述符。在Windows95中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员被忽略。bInheritHandles:指示新进程是否从调用进程处继承了句柄。如果参数的值为真,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限。dwCreationFlags:指定附加的、用来控制优先类和进程的创建的标志。以下的创建标志可以以除下面列出的方式外的任何方式组合后指定。值:CREATE_DEFAULT_ERROR_MODE含义:新的进程不继承调用进程的错误模式。CreateProcess函数赋予新进程当前的默认错误模式作为替代。应用程序可以调用SetErrorMode函数设置当前的默认错误模式。这个标志对于那些运行在没有硬件错误环境下的多线程外壳程序是十分有用的。对于CreateProcess函数,默认的行为是为新进程继承调用者的错误模式。设置这个标志以改变默认的处理方式。值:CREATE_NEW_CONSOLE含义:新的进程将使用一个新的控制台,而不是继承父进程的控制台。这个标志不能与DETACHED_PROCESS标志一起使用。值:CREATE_NEW_PROCESS_GROUP含义:新进程将使一个进程树的根进程。进程树种的全部进程都是根进程的子进程。新进程树的用户标识符与这个进程的标识符是相同的,由lpProcessInformation参数返回。进程树经常使用GenerateConsoleCtrlEvent函数允许发送CTRL+C或CTRL+BREAK信号到一组控制台进程。值:CREATE_SEPARATE_WOW_VDM含义:(只适用于WindowsNT)这个标志只有当运行一个16位的Windows应用程序时才是有效的。如果被设置,新进程将会在一个私有的虚拟DOS机(VDM)中运行。另外,默认情况下所有的16位Windows应用程序都会在同一个共享的VDM中以线程的方式运行。单独运行一个16位程序的优点是一个应用程序的崩溃只会结束这一个VDM的运行;其他那些在不同VDM中运行的程序会继续正常的运行。同样的,在不同VDM中运行的16位Windows应用程序拥有不同的输入队列,这意味着如果一个程序暂时失去响应,在独立的VDM中的应用程序能够继续获得输入。值:CREATE_SHARED_WOW_VDM含义:(只适用于WindowsNT)这个标志只有当运行一个16位的Windows应用程序时才是有效的。如果WIN.INI中的Windows段的DefaultSeparateVDM选项被设置为真,这个标识使得CreateProcess函数越过这个选项并在共享的虚拟DOS机中运行新进程。值:CREATE_SUSPENDED含义:新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行。值:CREATE_UNICODE_ENVIRONMENT含义:如果被设置,由lpEnvironment参数指定的环境块使用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任务列表,为了保证当用户调用时可以立刻响应,放弃了对系统负荷的考虑。确保在使用高优先级时应该足够谨慎,因为一个高优先级的CPU关联应用程序可以占用几乎全部的CPU可用时间。优先级:IDLE_PRIORITY_CLASS含义:指示这个进程的线程只有在系统空闲时才会运行并且可以被任何高优先级的任务打断。例如屏幕保护程序。空闲优先级会被子进程继承。优先级:NORMAL_PRIORITY_CLASS含义:指示这个进程没有特殊的任务调度要求。优先级:REALTIME_PRIORITY_CLASS含义:指示这个进程拥有可用的最高优先级。一个拥有实时优先级的进程的线程可以打断所有其他进程线程的执行,包括正在执行重要任务的系统进程。例如,一个执行时间稍长一点的实时进程可能导致磁盘缓存不足或鼠标反映迟钝。lpEnvironment:指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境。一个环境块存在于一个由以NULL结尾的字符串组成的块中,这个块也是以NULL结尾的。每个字符串都是name=value的形式。因为相等标志被当作分隔符,所以它不能被环境变量当作变量名。与其使用应用程序提供的环境块,不如直接把这个参数设为空,系统驱动器上的当前目录信息不会被自动传递给新创建的进程。对于这个情况的探讨和如何处理,请参见注释一节。环境块可以包含Unicode或ANSI字符。如果lpEnvironment指向的环境块包含Unicode字符,那么dwCreationFlags字段的CREATE_UNICODE_ENVIRONMENT标志将被设置。如果块包含ANSI字符,该标志将被清空。请注意一个ANSI环境块是由两个零字节结束的:一个是字符串的结尾,另一个用来结束这个快。一个Unicode环境块石油四个零字节结束的:两个代表字符串结束,另两个用来结束块。lpCurrentDirectory:指向一个以NULL结尾的字符串,这个字符串用来指定子进程的工作路径。这个字符串必须是一个包含驱动器名的绝对路径。如果这个参数为空,新进程将使用与调用进程相同的驱动器和目录。这个选项是一个需要启动启动应用程序并指定它们的驱动器和工作目录的外壳程序的主要条件。lpStartupInfo:指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。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_ACTIVE变为最后一个结束的线程的结束状态。*主线程的线程对象被设置为标志状态,供其他等待这个对象的线程使用。*进程对象被设置为标志状态,供其他等待这个对象的线程使用。假设当前在C盘上的目录是\MSVC\MFC且有一个环境变量叫做C:,它的值是C:\MSVC\MFC,就像前面lpEnvironment中提到过的那样,这样的系统驱动器上的目录信息在CreateProcess函数的lpEnvironment参数不为空时不会被自动传递到新进程里。一个应用程序必须手动地把当前目录信息传递到新的进程中。为了这样做,应用程序必须直接创建环境字符串,并把它们按字母顺序排列(因为WindowsNT和Windows95使用一种简略的环境变量),并把它们放进lpEnvironment中指定的环境块中。类似的,他们要找到环境块的开头,又要重复一次前面提到的环境块的排序。一种获得驱动器X的当前目录变量的方法是调用GetFullPathName("x:",..)。这避免了一个应用程序必须去扫描环境块。如果返回的绝对路径是X:\,就不需要把这个值当作一个环境数据去传递了,因为根目录是驱动器X上的新进程的默认当前目录。由CreateProcess函数返回的句柄对于进程对象具有PROCESS_ALL_ACCESS的访问权限。由lpcurrentDirectory参数指定的当前目录室子进程对象的当前目录。lpCommandLine参数指定的第二个项目是父进程的当前目录。对于WindowsNT,当一个进程在指定了CREATE_NEW_PROCESS_GROUP的情况下被创建时,一个对于SetConsoleCtrlHandler(NULL,True)的调用被用在新的进程上,这意味着对新进程来说CTRL+C是无效的。这使得上层的外科程序可以自己处理CTRL+C信息并有选择的把这些信号传递给子进程。CTRL+BREAK依旧有效,并可被用来中断进程/进程树的执行。
相关问题略懂社热议相关搜索
问问青春版,什么都略懂一点

参考资料

 

随机推荐