226上位机VC MFC调用外部程序完成不同任务
226上位机VC MFC调用外部程序完成不同任务 功能展示 在调用外部的程序时,可以同时向被调用的程序传入指令参数,当然前提是,被调用的程序得有接收指令参数的处理代码,我们当前例程编写了调用程序与被调用程序,实现调用外部程序完成不同任务的功能,效果如图; 要点提示 1.要想程序接收外部传入的命令,自序自身得有接收命令的代码,接收命令可以用函数GetCommandLine().我们只要在程序初始入口调用此函数,函数返回的字符串就是外部程序传入的指令;函数原型:LPTSTRGetCommandLine(VOID) 返回值就是接收的指令字符串指针; 接收的指令的格式可以自行定义,只要接收指令程序与调用程序能相互解析便可; 2.调用外部程序与此同时发送指令可以用函数CreateProcess() 函数原型:BOOL CreateProcess ( PCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); 参数说明: lpApplicationName 指向一个NULL结尾的、用来指定可执行模块的字符串。 这个字符串可以是可执行模块的绝对路径,也可以是相对路径,在后一种情况下,函数使用当前驱动器和目 录建立可执行模块的路径。 这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于lpCommandLine 参数最前面并由空格符与后面的字符分开。 lpCommandLine 指向一个以NULL结尾的字符串,该字符串指定要执行的命令行。 这个参数可以为空,那么函数将使用lpApplicationName参数指定的字符串当做要运行的程序的命令行。 如果lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数指定将被运行的模块的命令行。新运行的进程可以使用GetCommandLine函数获得整个命令行。C语言程序可以使用argc和argv参数。 lpProcessAttributes 指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。 在Windows NT中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了新进程的安全描述符,如果参数为空,新进程使用默认的安全描述符。 lpThreadAttributes 同lpProcessAttribute,不过这个参数决定的是线程是否被继承.通常置为NULL bInheritHandles 指示新进程是否从调用进程处继承了句柄。 如果参数的值为真,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限。 dwCreationFlags 指定附加的、用来控制优先类和进程的创建的标志,取值众多,可以查阅MSDN手册; dwCreationFlags参数 还用来控制新进程的优先类,优先类用来决定此进程的线程调度的优先级。如果下面的优先级类标志都没有被指定,那么默认的优先类是NORMAL_PRIORITY_CLASS,除非被创建的进程是IDLE_PRIORITY_CLASS。在这种情况下子进程的默认优先类是IDLE_PRIORITY_CLASS。 lpEnvironment 指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境。 一个环境块存在于一个由以NULL结尾的字符串组成的块中,这个块也是以NULL结尾的。每个字符串都是name=value的形式。 因为相等标志被当做分隔符,所以它不能被环境变量当做变量名。 与其使用应用程序提供的环境块,不如直接把这个参数设为空,系统驱动器上的当前目录信息不会被自动传递给新创建的进程。对于这个情况的探讨和如何处理,请参见注释一节。 环境块可以包含Unicode或ANSI字符。如果lpEnvironment指向的环境块包含Unicode字符,那么dwCreationFlags字段的CREATE_UNICODE_ENⅥRONMENT标志将被设置。如果块包含ANSI字符,该标志将被清空。 请注意一个ANSI环境块是由两个零字节结束的:一个是字符串的结尾,另一个用来结束这个快。一个Unicode环境块是由四个零字节结束的:两个代表字符串结束,另两个用来结束块。 lpCurrentDirectory 指向一个以NULL结尾的字符串,这个字符串用来指定子进程的工作路径。这个字符串必须是一个包含驱动器名的绝对路径。如果这个参数为空,新进程将使用与调用进程相同的驱动器和目录。这个选项是一个需要启动应用程序并指定它们的驱动器和工作目录的外壳程序的主要条件。 lpStartupInfo 指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。 lpProcessInformation 指向一个用来接收新进程的识别信息的PROCESS_INFORMATION结构体。 实现功能 1.新建基于对话框的应用程序,用于被外部程序调用,接收外部指令 2.在对话框初始化函数OnInitDialog()中实现接收外部指令功能 - //<>获取与显示指令
- CString sCommand;
- LPWSTR *pCmd = NULL;
- int nNum = 0;
- /*
- pCmd就是保存参数的数组
- nNum是数组中参数的个数
- 数组的第一个元素表示进程的path,也就是pCmd[0],其他的元素依次是输入参数。
- */
- pCmd = CommandLineToArgvW(GetCommandLineW(), &nNum);
- if( NULL != pCmd)
- {
- for(int i=0; i<nNum; i++)
- sCommand+=pCmd[i];
- SetDlgItemText(IDC_EDIT1,sCommand);
- }
- else
- AfxMessageBox("指令获取失败");
- LocalFree(pCmd);//取得参数后,释放CommandLineToArgvW申请的空间
- //<>执行指令
- CString sCmd=sCommand.Left(sCommand.Find('|')+1);
- sCommand.Delete(0,sCmd.GetLength());
- CString sArgu1=sCommand.Left(sCommand.Find('|')+1);
- sCommand.Delete(0,sArgu1.GetLength());
- CString sArgu2=sCommand;
-
复制代码- sCmd=sCmd.Left(sCmd.Find('|'));//具体指令
- sArgu1=sArgu1.Left(sArgu1.Find('|'));//指令参数1
- sArgu2=sArgu2.Left(sArgu2.Find('|'));//指令参数2
- if(sCmd=="新建文件")
- {
- CStdioFile file(sArgu1, CFile::modeReadWrite|CFile::modeCreate);
- file.WriteString("工控编程吧\r\n");
- file.WriteString("网址:gkbc8.com\r\n");
- if(sArgu2=="exit")
- exit(1);
- }
复制代码3.新建新基本对话框的应用程序,用于调用前面的程序,向其传入指令实现指定功能; 4.添加按钮控件,关联函数,实现调用外部程序传送指令参数,实现指定功能; - void CGkbc8Dlg::OnButton1()
- { TCHAR szPath[MAX_PATH];
- SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOP, FALSE); //桌面路径
- CString sCommand="新建文件|";
- sCommand+=szPath;
- sCommand+="\\gkbc8.txt|";
- sCommand+="exit||";
- //><
- SECURITY_ATTRIBUTES ProSec,ThreadSec;
- ProSec.bInheritHandle = TRUE;
- ProSec.nLength = sizeof(ProSec);
-
- ThreadSec.bInheritHandle = TRUE;
- ThreadSec.nLength = sizeof(ThreadSec);
- STARTUPINFO StrInfo;
- memset(&StrInfo,0,sizeof(StrInfo));
- StrInfo.cb = sizeof(StrInfo);
- PROCESS_INFORMATION ProcInfo;
- CreateProcess("be_called.exe",sCommand.GetBuffer(0),NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE,NULL,NULL,&StrInfo,&ProcInfo);}
复制代码我们来演示下功能实现的整个过程
|