实现外部程序根据参数调用、控制目标程序——ShellExecute()函数的详解及相关知识的拓展

本文主要是介绍实现外部程序根据参数调用、控制目标程序——ShellExecute()函数的详解及相关知识的拓展,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

喵哥最近在做一个需要远程控制相机的项目,其中一个环节就是需要用一个控制端的exe去调用相机运行的exe,还需要根据控制端提供的参数对相机作出相应的控制动作。另外,如果有做类似项目的朋友,希望可以交流一下经验,共同进步。

目录

WinExec

ShellExecute

接收参数


根据以往的经验,需要在外部执行文件开启一个程序的方法就是使用WinExec()函数,这个函数的参数简单,用起来也十分方便:

UINT WINAPI WinExec(_In_  LPCSTR lpCmdLine,_In_  UINT uCmdShow
);

WinExec

WinExec()的第一个参数是执行文件的路径,第二个参数是执行文件打开后的显示方式。在使用WinExec()时需要注意的事情:

************返回值**************** 
大于 31                    {调用成功}
等于 0 {内存不足}
ERROR_FILE_NOT_FOUND = 2;  {文件名错误}
ERROR_PATH_NOT_FOUND = 3;  {路径名错误}
ERROR_BAD_FORMAT     = 11; {EXE 文件无效}
(请参考FindExecutable函数) *************uCmdShow 参数可选值**************
SW_HIDE            = 0; {隐藏, 并且任务栏也没有最小化图标} SW_SHOWNORMAL = 1; {用最近的大小和位置显示, 激活}
SW_NORMAL          = 1; {同 SW_SHOWNORMAL}
SW_SHOWMINIMIZED   = 2; {最小化, 激活}
SW_SHOWMAXIMIZED   = 3; {最大化, 激活}
SW_MAXIMIZE        = 3; {同 SW_SHOWMAXIMIZED}
SW_SHOWNOACTIVATE  = 4; {用最近的大小和位置显示, 不激活}
SW_SHOW            = 5; {同 SW_SHOWNORMAL}
SW_MINIMIZE        = 6; {最小化, 不激活}
SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE}
SW_SHOWNA          = 8; {同 SW_SHOWNOACTIVATE}
SW_RESTORE         = 9; {同 SW_SHOWNORMAL}
SW_SHOWDEFAULT     = 10; {同 SW_SHOWNORMAL}
SW_MAX             = 10; {同 SW_SHOWNORMAL} 

另外,winexec() 必须有GetMessage或超时之后才返回!


ShellExecute

WinExec的一大缺点就是没有参数的传递机制,其实如果目标执行文件的参数不多,并且调用目标函数时使用的参数是有规律的,那么其实可以把参数放在一个文件中保存,然后顺序读取参数即可,也可以实现根据参数来控制目标执行文件的启动,但是喵哥的项目需要不按参数顺序来启动执行文件,或者说考虑到以后程序的扩展性,所以放弃了这个函数,然后在网上寻找合适的替代品。然后找到一说WinExec就不得不说的ShellExecute。

ShellExecute()函数的参数表要比WinExec大,有6个参数:

HINSTANCE ShellExecute(_In_opt_  HWND hwnd,  _In_opt_  LPCTSTR lpOperation, _In_      LPCTSTR lpFile,  _In_opt_  LPCTSTR lpParameters, _In_opt_  LPCTSTR lpDirectory, _In_      INT nShowCmd
);

各个参数的说明如下:

hWnd:用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。例如,可以将其设置为应用程序主窗口句柄,即Application.Handle,也可以将其设置为桌面窗口句柄(用GetDesktopWindow函数获得)。 
     Operation:用于指定要进行的操作。其中“open”操作表示执行由FileName参数指定的程序,或打开由FileName参数指定的文件或文件夹;“print”操作表示打印由FileName参数指定的文件;“explore”操作表示浏览由FileName参数指定的文件夹。当参数设为nil时,表示执行默认操作“open”。 
      FileName:用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。 
      Parameters:若FileName参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为nil或PChar(0)。 
      Directory:用于指定文件开始运行的默认目录,即FileName为NULL时,打开该文件夹,若不对默认目录做出设置(NULL),默认打开文档(环境为Windows 10)。 
      ShowCmd:若FileName参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。这个参数可用的值如下所列:

1 SW_HIDE 隐藏这个窗体,并激活其他窗体。
2 SW_MAXIMIZE 最大化指定的窗体。
3 SW_MINIMIZE 最小化指定的窗体,并按顺序激活最上层的窗体。
4 SW_RESTORE 激活并显示窗体。如果窗体为最小化或者最大化,窗体恢复到原始大小和位置。应用程序当恢复一个最小化的窗体时将指定标记。
5 SW_SHOW 以当前的大小和位置激活并显示窗体。
6 SW_SHOWDEFAULT 
7 SW_SHOWMAXIMIZED 激活并最大化显示窗体。
8 SW_SHOWMINIMIZED 激活并最小化现实窗体。
9 SW_SHOWMINNOACTIVE 最小化窗体,保持其激活状态。
10 SW_SHOWNA 以当前状态显示窗体,保持其激活状态。
11 SW_SHOWNOACTIVATE 以当前的大小和位置显示窗体,并保持其激活状态。
12 SW_SHOWNORMAL 激活并显示一个窗体。如果窗体为最大化或者最小化,窗体恢复到原始的大小和位置。当窗体第一次显示的时候,应用程序记录标记。

若ShellExecute函数调用成功,则返回值为被执行程序的实例句柄。若返回值小于32,则表示出现错误。


ShellExecute的功能远不止这些,它还可以做一些特别酷的事情:

1. 如果将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); 
      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.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。 

还有其他一些有意思的操作可以参考:深入浅出ShellExecute(总结)。

除了ShellExecute()之外,还有一个比较复杂、又强大的函数——CreateProcess(),其函数原型如下:

BOOL WINAPI CreateProcess(_In_opt_     LPCTSTR lpApplicationName,_Inout_opt_  LPTSTR lpCommandLine,_In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,_In_opt_     LPSECURITY_ATTRIBUTES lpThreadAttributes,_In_         BOOL bInheritHandles,_In_         DWORD dwCreationFlags,_In_opt_     LPVOID lpEnvironment,_In_opt_     LPCTSTR lpCurrentDirectory,_In_         LPSTARTUPINFO lpStartupInfo,_Out_        LPPROCESS_INFORMATION lpProcessInformation
);

由于CreateProcess比较复杂,而ShellExecute还可以满足需求,所以暂时没有认真去了解它。有兴趣的朋友可以去看:https://blog.csdn.net/duck04551/article/details/4312260。


接收参数

所以喵哥最终选用了ShellExecute()函数来控制目标执行文件,但是还有一个问题需要解决,那就是目标执行文件怎么接收ShellExecute发过去的参数呢,为此喵哥又去研究了一下main函数的参数传递规律。

先从最简单的 int main(int argc, char * argv)开始,喵哥最开始接触C/C++时,对于这个主函数的参数定义十分不屑(主要是无知...)觉得我用main()不一样用得挺好嘛,也一直没用到过这两个参数,直到最近几天,我突然意识到外部跟程序的参数传递可以通过这俩参数,真是惊醒梦中人。

为了测试传递参数的规律,我写了如下简单的测试代码:

int main(int argc, char *argv[])
{int i;for (i = 0; i < argc; i++)printf("Argument %d is %s.\n", i, argv[i]);getchar();return 0;
}

然后在cmd中执行生成的exe文件:

根据cmd中的运行结果,可以得出一些结论。第一个参数argc,指明有多少个参数将被传递给主函数main(),真正的参数以字符串数组(即第2个参数argv[])的形式来传递。需要注意的是,argc代表参数的数量, main()函数本身是在索引0为的第一参数。 所以, argc总是至少为1,它的数值是argv列阵的元素数目。 所以, argv[0]的值是至关重要的。 如果用户在控制台环境中程序名称后键入含参数的指令, 那么随后的参数将传递给argv[1]。


熟悉MFC的朋友都知道,APP源代码中的InitInstance()相当于C++main函数,即程序的入口,在这里就可以接收命令传递过来的参数,并作出相应的操作。不过在MFC中argc和argv分别变成__argc和__argv,以下是我的部分代码。

/*****************接收ShellExecute的消息************************/CString str;for (int i = 1; i < __argc; i++){str += __argv[i];     }/***************************设置INDEX以选择需要的相机**********************/if (str == "openCamera1")       INDEX = 0;else if (str == "openCamera2")	INDEX = 1;else if (str == "openCamera3")	INDEX = 2;else if (str == "openCamera4")	INDEX = 3;else if (str == "openCamera5")	INDEX = 4;else if (str == "openCamera6")	INDEX = 5;else                            INDEX = 0;

 

这篇关于实现外部程序根据参数调用、控制目标程序——ShellExecute()函数的详解及相关知识的拓展的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/626299

相关文章

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

CSS3中的字体及相关属性详解

《CSS3中的字体及相关属性详解》:本文主要介绍了CSS3中的字体及相关属性,详细内容请阅读本文,希望能对你有所帮助... 字体网页字体的三个来源:用户机器上安装的字体,放心使用。保存在第三方网站上的字体,例如Typekit和Google,可以link标签链接到你的页面上。保存在你自己Web服务器上的字