Login dark

`
title: vc中调用其他应用:winexec、shellexecute、createprocess
author: Love02xp
date: 2019-08-15 01:42:58
category: [编程代码]
tags: [代码,VC6]


目前知道三种方式:WinExec,ShellExecute ,CreateProcess,别人已经总结的很好了《vc中调用其他应用程序的方法(函数) winexec,shellexecute ,createprocess》,我全文转载一下,另外后面加点自己的总结(黑体部分,除了标题)。



<!--more-->


目前知道三种方式:WinExec,ShellExecute ,CreateProcess,别人已经总结的很好了《vc中调用其他应用程序的方法(函数) 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 等等,就不会出现正常的 窗体,但是已经被加到任务列表里了。
这个函数只能打开exe文件。
需要的头文件:windows.h,winbase.h(前者是试验出来,后者是msdn上说明),另外,这两者的先后顺序不能变。
msdn上的说明:[url]http://msdn.microsoft.com/en-us/library/ms687393[/url](VS.85).aspx 
(二)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", "[url]http://www.google.com/[/url]", NULL, NULL, SW_SHOWNORMAL); // 打开网页[url]www.google.com[/url] 
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不支持定向输出。
这个函数可以打开任意文件,会调用系统注册的程序来打开对应后缀名的文件。
需要的头文件:windows.h,shellapi.h(前者是我试验出来的,后者是msdn说需要的)。另外这两者的先后顺序不能变。
msdn上说明:[url]http://msdn.microsoft.com/en-us/library/bb762153[/url](VS.85).aspx 
(三)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);
这个函数可以打开任意文件,会调用系统注册的程序来打开对应后缀名的文件。
需要的头文件:windows.h,winbase.h(前者是试验出来,后者是msdn上说明),另外,这两者的先后顺序不能变。
msdn上的说明:[url]http://msdn.microsoft.com/en-us/library/ms682425[/url](VS.85).aspx
可以看出,通过上面的几个不同的方法,都可以实现在应用程序中打开其他应用程序的目的,其中有些方法可能会麻烦一点,所以就需要我们根据不同的目的去选择最适合自己的方法去实现自己的目的! 
关于三个SDK函数: WinExec, ShellExecute,CreateProcess 的其他注意事项: 
1、定义头文件
原作者的内容删去。
这个是引用新函数都必须注意的内容。但是MS的头文件引用顺序有点怪,比如上面的三种清理。另外,如果用了预编译,那么记得在任何源程序中的#include “stdafx.h”之前的引用都会失效,从其后才生效。(不可否认,预编译有他的好处,尤其当程序很大的时候,但是任何好处都是要付出代价的)
2、定义路径
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)
3、注意文件的路径
在程序a调用程序b的时候,b原来的默认的当前路径都会变成a的当前路径。所以,一定要注意。
可以养成使用绝对路径的习惯,另外,记得打开文件之类的操作,一定要验证是否有错。

1,WinExec():
 
  WinExec主要运行EXE文件,不能运行其他类型的文件。不用引用特别单元。
 
  原型:UINT WinExec(exePath,ShowCmd)
 
  示例,我想要用记事本打开"C:\HDC.TXT",以正常方式运行:WinExec(pChar('notepad c:\taoyoyo.txt'),SW_SHOWNORMAL); 
 
  参数说明:
  --xePath:命令行参数。注意,要用pChar转化一下。
  --ShowCmd:外部程序的运行方式。其取值如下: 
  ```-SW_HIDE 隐藏 
  ```-SW_MAXIMIZE 最大化 
  ```-SW_MINIMIZE 最小化,并把Z order顺序在此窗口之后(即窗口下一层)的窗口激活 
  ```-SW_RESTORE 激活窗口并还原为初始化大小 SW_SHOW 以当前大小和状态激活窗口 
  ```-SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态 
  ```-SW_SHOWDEFAULT 以默认方式运行
  ```-SW_SHOWMAXIMIZED 激活窗口并最大化 
  ```-SW_SHOWMINIMIZED 激活窗口并最小化 
  ```-SW_SHOWMINNOACTIVE 最小化但不改变当前激活的窗口 
  ```-SW_SHOWNA 以当前状态显示窗口但不改变当前激活的窗口 
  ```-SW_SHOWNOACTIVATE 以初始化大小显示窗口但不改变当前激活的窗口 
  ```-SW_SHOWNORMAL 激活并显示窗口,如果是最大(小)化,窗口将会还原。第一次运行程序 时应该使用这个值 
 
  如果调用成功,这个函数会返回一个不小于31的值,否则调用失败,其返回值的意义如下:
  --0 系统内存或资源不足 
  --ERROR_BAD_FORMAT .EXE文件格式无效(比如不是32位应用程序) 
  --ERROR_FILE_NOT_FOUND 指定的文件设有找到
  --ERROR_PATH_NOT_FOUND 指定的路径没有找到
 
  其他:
  这个函数和system()非常类似,只能运行.EXE文件,这样在WINDOWS中有它不尽人意的地方,比如不能用此方法通过关联的方法打开文件,例如WinExec("1.html",SW_SHOWNA);就不能打开此文档。
 
  2,ShellExecute() :
 
  不仅可以运行EXE文件,也可以运行系统已经关联的文件。
  这个函数和WIN9X中的命令行命令"start"类似,不光可以对文件进行操作,还可以对HTTP、MAILTO等进行操作。这样我们可以设计有超级链接风格的程序了。
  ShellExecute的功能要强得多,并且可以完全替代WinExec(),事实上,WinExec()也是为了和以前版本兼容而保留,所以,我们要尽量使用ShellExecute()。
 
  首先必须引用shellapi.pas单元:uses ShellAPI; 
 
  函数原型:function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,Directory: PChar; ShowCmd: Integer): HINST; stdcall; 
 
  参数含义如下: 
 
  --hWnd:用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。例如,可以将其设置为应用程序主窗口句柄,即Application.Handle,也可以将其设置为桌面窗口句柄(用GetDesktopWindow函数获得)。 
  --Operation:用于指定要进行的操作。
  ```-open:操作表示执行由FileName参数指定的程序,或打开由FileName参数指定的文件或文件夹;
  ```-print:操作表示打印由FileName参数指定的文件;
  ```-explore:操作表示浏览由FileName参数指定的文件夹。
  ```-为nil时,表示执行默认操作“open”。 
  --FileName:用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。 
  --Parameters:若FileName参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为nil或PChar(0)。 
  --Directory:用于指定默认目录。 
  --ShowCmd:若FileName参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。 
  ```-SW_HIDE 隐藏 
  ```-SW_MAXIMIZE 最大化 
  ```-SW_MINIMIZE 最小化,并把Z order顺序在此窗口之后(即窗口下一层)的窗口激活 
  ```-SW_RESTORE 激活窗口并还原为初始化大小 SW_SHOW 以当前大小和状态激活窗口 
  ```-SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态 
  ```-SW_SHOWDEFAULT 以默认方式运行
  ```-SW_SHOWMAXIMIZED 激活窗口并最大化 
  ```-SW_SHOWMINIMIZED 激活窗口并最小化 
  ```-SW_SHOWMINNOACTIVE 最小化但不改变当前激活的窗口 
  ```-SW_SHOWNA 以当前状态显示窗口但不改变当前激活的窗口 
  ```-SW_SHOWNOACTIVATE 以初始化大小显示窗口但不改变当前激活的窗口 
  ```-SW_SHOWNORMAL 激活并显示窗口,如果是最大(小)化,窗口将会还原。第一次运行程序 时应该使用这个值 
 
  若ShellExecute函数调用成功,则返回值为被执行程序的实例句柄。若返回值小于32,则表示出现错误。 
 
  示例:
 
  (1),刚才的例子:WinExec(pChar('notepad c:\taoyoyo.txt'),SW_SHOWNORMAL); 
  就可以改变为(假设窗口的句柄为Handle) 
  ShellExecute(Handle,'open','notepad','c:\taoyoyo.txt','',SW_SHOWNORMAL); 
 
  此外,还可以不用那么复杂,因为.TXT的关联程序就是记事本,所以只要这样就可以了:
  ShellExecute(Handle,'','c:\taoyoyo.txt','','',SW_SHOWNORMAL); 
 
  (2),例子(delphi): 
  在一个应用程序调用c:Project1.exe; 
  ShellExecute(handle, 'open','c:Project1.exe','字串内容',nil, SW_SHOWNORMAL); 
 
  在Project1.exe里可以调用: 
  procedure TForm1.FormCreate(Sender: TObject); 
  var i:integer; 
  begin 
  for i:=1 to paramcount do 
  if ParamStr(i)〈〉'' then showmessage(ParamStr(i)); 
  end;  
 
  (3),在VB中,我们首先声明此函数(可由VB自带的API游览器得到): 
  Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long 
 
  然后放置两个Label,设置其属性为: 
  Name lbHomepage lbEMail Caption http://bcbtop.126.com mailto:hugsnow@126.com 
 
  并把字体改为蓝色有下划线,然后分别在两个Label的Click事件中加入以下代码: 
 
  ShellExecute(Me.hWnd,"",lbHomepage.Caption,"","",SW_SHOWNORMAL); 
  ShellExecute(Me.hWnd,"",lbEMail.Caption,"","",SW_SHOWNORMAL); 
 
  3,ShellExecute() 特殊用法 
 
  如果将FileName参数设置为“http:”协议格式,那么该函数将打开默认浏览器并链接到指定的URL地址。若用户机器中安装了多个浏览器,则该函数将根据Windows 9x/NT注册表中http协议处理程序(Protocols Handler)的设置确定启动哪个浏览器。 
 
  格式一:http://网站域名。 
  如:ShellExecute(handle, 'open', http:// ; www.neu.edu.cn', nil, nil, SW_SHOWNORMAL); 
 
  格式二:http://网站域名/网页文件名。 
  如:ShellExecute(handle, 'open', http:// ; www.neu.edu.cn/default.htm',nil,nil, SW_SHOWNORMAL); 
 
  如果将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.neu.edu.cn', nil, nil, SW_SHOWNORMAL);打开新邮件窗口,并自动填入收件人地址。若指定多个收件人地址,则收件人地址之间必须用分号或逗号分隔开(下同)。 
 
  格式三:mailto:用户账号@邮件服务器地址?subject=邮件主题&body=邮件正文 
  如:ShellExecute(handle, 'open', ' mailto:who@mail.neu.edu.cn?subject=Hello&Body=This is a test', nil, nil, SW_SHOWNORMAL);打开新邮件窗口,并自动填入收件人地址、邮件主题和邮件正文。若邮件正文包括多行文本,则必须在每行文本之间加入换行转义字符%0a。 
 
 
 
 
  ===============
  其它文章:
 
  介绍一个功能强大的API函数 ShellExecute 
 
  编译 赵湘宁 
 
  问题的提出:
  我使用MFC编写一个APP,要求About对话框中显示LOGO、公司名、地址和公司的URL链接。使用户点击URL链接以后,启动浏览器访问Web页面,这种对话框中的热链接使应用程序增色不少。我琢磨的方法是从系统注册表中通过查找.htm 或 .html文件的关联程序来获得缺省浏览器的名字,这样好象有很多工作要做。此外,如果浏览器已经打开,总是开始一个新的实例替代当前已有的一个实例。想找一个容易一点的方法,但我查过有关的资料,没有收获,请高手指教。 
 
  解决方法:
  如果有这样的一个API函数该多好:OpenThisHereURLForMeNowPlease(),问题不就解决了!!我告诉你吧,有,但它不是你所想象的那个函数。到目前为止,有关文档中还没有提到过这么一个有用的函数,它能打开桌面上的任何文件,也能打开Internet URL。唯一我能找到的参考资料是在Microsoft&reg; Access KnowledgeBase中很暧昧地提到过这个函数。
  这个不可思议的函数就是:ShellExecute,取代了WinExec。你可以给它任何文件的名字,它都能识别出来并打开它。例如:
 
  ShellExecute(NULL,"open","iloveu.bmp",NULL,NULL,SW_SHOWNORMAL);
 
  用缺省的位图编辑器打开一个叫iloveu.bmp的位图文件,这个缺省的位图编辑器可能是Microsoft Paint, Adobe Photoshop, 或者 Corel PhotoPaint。
 
  有关ShellExecute的详细用法信息自己去参考有关资料吧,重要的是你知道了这个函数能打开任何文件,甚至是桌面和URL快捷方式( .ink或 .url)。ShellExecute解析系统注册表HKEY_CLASSES_ROOT中所有的内容,判断启动那一个执行程序,并且启动一个新的实例或使用DDE将文件名连到一打开的实例。然后,ShellExecute 返回打开文件的应用的实例句柄。
 
  更奇妙的是ShellExecute不仅能打开机器上的文件,还能打开Internet的站点地址。例如:
 
  ShellExecute(NULL, "open", "http://www.microsoft.com", NULL, NULL, SW_SHOWNORMAL);  
  这个代码使你能访问微软的主页。当ShellExecute遇到文件名前面的“http:”时,可以判断出要打开的文件是Web文件,随之启动Internet Explorer 或者 Netscape Navigator 或者任何你使用的别的浏览器打开文件。ShellExecute还能识别其它协议,象FTP、GOPHER。甚至识别“mailto”,如果文件名指向“mailto:zxn@hq.cninfo.net”,它启动电子邮件程序并打开一个待编辑的新邮件。总之,ShellExecute函数就是如此简单地打开磁盘文件和Internet文件。如果将第二个参数“OPEN”改为“PRINT”或者“EXPLORE”,ShellExecute将能打印文件和打开文件夹。ShellExecute还有一个扩展函数ShellExecuteEx,所带参数中有一个特殊的结构,功能更强,它的用法参见有关文档。
 
  现在,你知道了ShellExecute的秘密,用它很容易增加一个链接到你的About对话框。不是吗。
 
  怎样加载其他的应用程序?  
 
  三个SDK函数 winexec, shellexecute,createprocess可以使用。WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。
  ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:\temp\1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦.
 
  ShellExecute(NULL,NULL,_T("1.txt",NULL,_T("c:\\temp",SW_SHOWMAXMIZED)
 
  CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:
 
  STARTUPINFO stinfo
  //启动窗口的信息
  PROCESSINFO procinfo //进程的信息
  CreateProcess(NULL,_T("notepad.exe",NULL,NULL.FALSE,
  NORMAL_PRIORITY_
  CLASS,NULL,NULL, &stinfo,&procinfo)