打造自己的GUI专版命令行程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
打造自己的GUI专版命令行程序
命令行下的工具效率高,速度快,但是当程序的参数太多时,却不易于使用。所以我们就给它做个界面封装一下,顺便把我们的大名也加上呵呵为了方便说明我们选用一个比较简单的程序GetOS.exe它是MS04011工具包中的一个小工具,主要用来探测目标系统的类型原程序和改造后的效果如图1和图2所示
实现思路:
现在主要有两个问题需解决
1.怎样在GUI程序中把参数传递给CMD程序
2.怎样把结果传回到界面
这两个问题可以用CreateProcess结合管道来解决,可以用CreateProcess创建CMD程序并传递需要参数
执行完成后再将结果写到指定的管道中去,最后把管道的内容更新到界面程序的控件中。
结构说明:
在开始之前先看几个比较重要的结构和API函数
CreateProcess用来创建新的进程它的的原形如下:
BOOL CreateProcess(
LPCTSTR lpApplicationName,
// pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_A TTRIBUTES lpProcessAttributes, // process security attributes
LPSECURITY_A TTRIBUTES lpThreadAttributes, // thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMA TION lpProcessInformation // pointer to PROCESS_INFORMA TION
);
lpApplicationName和lpCommandLine参数分别用于新进程用使用的文件名,和要传递给新进程的参数
字符串
通常把lpApplicationName置为NULL而在lpCommandLine中给出程序的全路径和参数字符串。
bInheritHandles用来指定子进程是否继承主进程的句柄。
lpStartupInfo是程序的要点,它用于指向一个STARTUPINFO结构,其定义如下:
typedef struct _STARTUPINFO ...{ // si
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
这个结构有很多项,需要使用的有以下几项
WORD wShowWindow; //是否显示调用
HANDLE hStdOutput; //子程序输出句柄
HANDLE hStdError; //子程序错误输出句柄
DWORD dwFlags; //创建子进程的一组标志
只要让hStdOutput句柄指向管道的写句柄,程序执行后结果就保存在管道中了。
-
>
参数传递:
跟据上面的说明在创建子进程时,可以这样构建参数传递命令
char szCMD[]="c:\getos.exe";
UpdateData(true);
if(m_szIP!="") \m_szIP为EDIT控件用于接受目标IP
...{
char* szIP=m_szIP.LockBuffer();
sprintf(szCMD,"%s %s",szCMD,szIP);//构建参数传递命令
CreateProcess(NULL,szCMD,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi);//创建进程
}
结果写入管道:
SECURITY_ATTRIBUTES sa;
PROCESS_INFORMA TION pi;
STARTUPINFO si;
HANDLE hRead;
HANDLE hWrite;
sa.nLength = sizeof(SECURITY_A TTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CreatePipe(&hRead,&hWrite,&sa,0); //创建管道
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si); //设置启动信息
si.hStdError = hWrite;
si.hStdOutput = hWrite; //将子进程输出结果写出管道
si.wShowWindow = SW_HIDE; //隐式调用子程序
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
CreateProcess(NULL,szCMD,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi);
把子程序的输出写入管道,当子程序执行后就可以用ReadFile来读取管道的内容
读取管道内容:
char buffer[4096] = ...{0};
DWORD bytesRead;
ReadFile(hRead,buffer,4095,&bytesRead,NULL);//读取管道内容
m_edit+=buffer; //更新显示控件
UpdateData(false);
加载资源:
在完成上面的工作以前应该先把CMD程序以资源的形式加载进去,在使用时再释放出来。加载资源可按
以下步骤