冷风 打造自己的GUI专版命令行程序

本文介绍如何将命令行程序封装成带图形用户界面(GUI)的版本,通过使用CreateProcess结合管道来传递参数及获取结果,使命令行工具更易于使用。

注:本文于07/4月于黑客防线发表版权归黑客防线所有,转载请注明出处

打造自己的GUI专版命令行程序

文/图 德州科技职业学院 冷风

命令行下的工具效率高,速度快,但是当程序的参数太多时,却不易于使用。所以我们就给它做个界面封装一下,顺便把我们的大名也加上呵呵为了方便说明我们选用一个比较简单的程序GetOS.exe它是MS04011工具包中的一个小工具,主要用来探测目标系统的类型原程序和改造后的效果如图1和图2所示

实现思路:

现在主要有两个问题需解决
1.怎样在GUI程序中把参数传递给CMD程序
2.怎样把结果传回到界面

这两个问题可以用CreateProcess结合管道来解决,可以用CreateProcess创建CMD程序并传递需要参数
执行完成后再将结果写到指定的管道中去,最后把管道的内容更新到界面程序的控件中。

结构说明:
在开始之前先看几个比较重要的结构和API函数

CreateProcess用来创建新的进程它的的原形如下:
BOOLCreateProcess(
LPCTSTRlpApplicationName,
//pointertonameofexecutablemodule
LPTSTRlpCommandLine,//pointertocommandlinestring
LPSECURITY_ATTRIBUTESlpProcessAttributes,//processsecurityattributes
LPSECURITY_ATTRIBUTESlpThreadAttributes,//threadsecurityattributes
BOOLbInheritHandles,//handleinheritanceflag
DWORDdwCreationFlags,//creationflags
LPVOIDlpEnvironment,//pointertonewenvironmentblock
LPCTSTRlpCurrentDirectory,//pointertocurrentdirectoryname
LPSTARTUPINFOlpStartupInfo,//pointertoSTARTUPINFO
LPPROCESS_INFORMATIONlpProcessInformation//pointertoPROCESS_INFORMATION
);

lpApplicationName和lpCommandLine参数分别用于新进程用使用的文件名,和要传递给新进程的参数

字符串
通常把lpApplicationName置为NULL而在lpCommandLine中给出程序的全路径和参数字符串。
bInheritHandles用来指定子进程是否继承主进程的句柄。
lpStartupInfo是程序的要点,它用于指向一个STARTUPINFO结构,其定义如下:
typedef
struct_STARTUPINFO...{//si
DWORDcb;
LPTSTRlpReserved;
LPTSTRlpDesktop;
LPTSTRlpTitle;
DWORDdwX;
DWORDdwY;
DWORDdwXSize;
DWORDdwYSize;
DWORDdwXCountChars;
DWORDdwYCountChars;
DWORDdwFillAttribute;
DWORDdwFlags;
WORDwShowWindow;
WORDcbReserved2;
LPBYTElpReserved2;
HANDLEhStdInput;
HANDLEhStdOutput;
HANDLEhStdError;
}
STARTUPINFO,*LPSTARTUPINFO;

这个结构有很多项,需要使用的有以下几项

WORDwShowWindow;
//是否显示调用
HANDLEhStdOutput;//子程序输出句柄
HANDLEhStdError;//子程序错误输出句柄
DWORDdwFlags;//创建子进程的一组标志

只要让hStdOutput句柄指向管道的写句柄,程序执行后结果就保存在管道中了。

参数传递:

跟据上面的说明在创建子进程时,可以这样构建参数传递命令

charszCMD[]="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_ATTRIBUTESsa;
PROCESS_INFORMATIONpi;
STARTUPINFOsi;
HANDLEhRead;
HANDLEhWrite;

sa.nLength
=sizeof(SECURITY_ATTRIBUTES);
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来读取管道的内容

读取管道内容:

charbuffer[4096]=...{0};
DWORDbytesRead;
ReadFile(hRead,buffer,
4095,&bytesRead,NULL);//读取管道内容
m_edit+=buffer;//更新显示控件
UpdateData(false);

加载资源:

在完成上面的工作以前应该先把CMD程序以资源的形式加载进去,在使用时再释放出来。加载资源可按

以下步骤
在Resource右键选择IMPORT选择文件然后输入类型(比如GETOS)就行了,在使用时可用以下代码释放

HRSRChr
=FindResource(0,MAKEINTRESOURCE(IDR_GETOS),"GETOS");/查找资源
if(hr==NULL)
MessageBox(
"hrerror");

dwSize
=SizeofResource(NULL,hr);

HGLOBALhg
=LoadResource(NULL,hr);//加载资源

if(hg==NULL)
MessageBox(
"hgerror");

LPSTRlp
=(LPSTR)LockResource(hg);//锁定资源

if(lp==NULL)
MessageBox(
"lperror");

HANDLEhFile;
hFile
=CreateFile("c:/getos.exe",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);//创建文件
if(hFile==NULL)
MessageBox(
"fileerror");
WriteFile(hFile,(LPCVOID)LockResource(hg),dwSize,
&dwWritten,NULL);//写入文件
CloseHandle(hFile);

结合上面内容现在你可以把自己钟意的CMD程序为自己做个GUI专版喽......

注:本文于07/4月于黑客防线发表版权归黑客防线所有,转载请注明出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值