命令行下的工具效率高,速度快,但是當程序的參數太多時,卻不易於使用。所以我們就給它做個界面封裝一下,順 便把我們的大名也加上呵呵為了方便說明我們選用一個比較簡單的程序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_ATTRIBUTES lpProcessAttributes, // process security attributes
LPSECURITY_ATTRIBUTES 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_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
);
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_INFORMATION pi;
STARTUPINFO si;
HANDLE hRead;
HANDLE hWrite;
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來讀取管道的內容
讀取管道內容:

char buffer[4096] = ...{0};
DWord bytesRead;
ReadFile(hRead,buffer,4095,&bytesRead,NULL);//讀取管道內容
m_edit+=buffer; //更新顯示控件
UpdateData(false);
加載資源:
在完成上面的工作以前應該先把CMD程序以資源的形式加載進去,在使用時再釋放出來。加載資源可按
以下步驟
在Resource右鍵選擇IMPORT選擇文件然後輸入類型(比如GETOS)就行了,在使用時可用以下代碼釋放
HRSRC hr=FindResource(0,MAKEINTRESOURCE(IDR_GETOS),"GETOS");\查找資源
if(hr==NULL)
MessageBox("hr error");
dwSize=SizeofResource(NULL,hr);
HGLOBAL hg=LoadResource(NULL,hr);//加載資源
if(hg==NULL)
MessageBox("hg error");
LPSTR lp=(LPSTR)LockResource(hg);//鎖定資源
if(lp==NULL)
MessageBox("lp error");
HANDLE hFile;
hFile = CreateFile("c:\getos.exe",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);//創建文件
if(hFile == NULL)
MessageBox("file error");
WriteFile(hFile,(LPCVOID)LockResource(hg),dwSize,&dwWritten,NULL);//寫入文件
CloseHandle(hFile);