/
// //
// ------- 如何使cmd的输入和输出重定向到管道中 ------- //
// ------- 用这种方法可以将指令写入cmd并抓取输出 ------- //
// //
// --------- chendana's implements, modified by chenth --------- //
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
HANDLE hRead1,hWrite1; //读句柄,写句柄
HANDLE hRead2,hWrite2; //读句柄,写句柄
HANDLE hCmd;
int CreateCMD(HANDLE &hReadPipe1,HANDLE &hWritePipe1,//匿名管道1读写句柄
HANDLE &hReadPipe2,HANDLE &hWritePipe2,//匿名管道2读写句柄
HANDLE &hProcess)//创建的CMD.EXE进程句柄
{
int ret;
SECURITY_ATTRIBUTES sa;
sa.nLength=12;
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=true;
ret=CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0);
if (ret == 0)
{
return -1;
}
ret=CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0);
if (ret == 0)
{
return -1;
}
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow = SW_SHOW;//SW_HIDE
//创建进程且重定向标准输入输出
//将其标准输入设置为hReadPipe2
//将其标准输出和错误输出设置为hWritePipe1
//通信逻辑见上图
si.hStdInput = hReadPipe2;
si.hStdOutput = si.hStdError = hWritePipe1;
char cmdLine[] = "cmd";
PROCESS_INFORMATION ProcessInformation;
ret=CreateProcess(NULL,(LPSTR)cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInformation);
if (ret == 0)
{
return -1;
}
hProcess=ProcessInformation.hProcess;
return 0;
}
//****************************************************************************
//此函数用来写已建立的管道
int WriteCMD(char* cmdBuffer,HANDLE hWritePipe2)
{
DWORD lBytesWrite;
char cmd_tmp[1024]="";
printf("writing.../n");
sprintf_s(cmd_tmp,1024,"%s%s",cmdBuffer,"/r/n");
if (!WriteFile(hWritePipe2,(LPTSTR)cmd_tmp,strlen(cmd_tmp),&lBytesWrite,NULL))
{
return -1;
}
return 0;
}
//****************************************************************************
//此函数用来读已建立的管道
int ReadCMD(HANDLE hReadPipe1,string &cmdResult){
BOOL ret;
DWORD lBytesRead;
char *buffer=new char [1024];
while(true)
{
printf("reading.../n");
Sleep(99);
memset(buffer,0,1024);
ret=ReadFile(hReadPipe1,buffer,1023,&lBytesRead,0);
if (ret == 0)
{
delete buffer;
return -1;
}
buffer[lBytesRead]='/0';
cmdResult += buffer;
if(buffer[lBytesRead-1]=='>')
{
delete buffer;
return 0;
}
}
delete buffer;
return 0;
}
//*****************************************************************************
//此函数用来关闭管道
void CloseCMD(HANDLE hReadPipe1,HANDLE hWritePipe1,//匿名管道1读写句柄
HANDLE hReadPipe2,HANDLE hWritePipe2,//匿名管道2读写句柄
HANDLE hProcess)//创建的CMD.EXE进程句柄
{
CloseHandle(hReadPipe1);
CloseHandle(hWritePipe1);
CloseHandle(hWritePipe2);
CloseHandle(hReadPipe2);
TerminateProcess(hProcess,0);
}
//*****************************************************************************
//此函数用来清空管道数据
void EmptyPipe(HANDLE hReadPipe1){
BOOL ret;
DWORD bytesRead;
char *buffer=new char [1024];
while(true)
{
memset(buffer,0,1024);
ret=PeekNamedPipe(hReadPipe1,buffer,1024,&bytesRead,0,0);
if (bytesRead==0||!ret)
{
delete buffer;
return;
}
ReadFile(hReadPipe1,buffer,bytesRead,&bytesRead,0);
}
}
// ------------------ Sample codes by chenth ------------------ //
int main( int argc, char *argv[] )
{
string result;
DWORD dw;
if (CreateCMD(hRead1,hWrite1,hRead2,hWrite2,hCmd) < 0)
{
printf("CreateCMD 失败 ");
dw = GetLastError();
printf("GetLastError-->%u/n", dw);
ExitProcess(dw);
return -1;
}
if (WriteCMD("dir",hWrite2) < 0)
{
printf("WriteCMD 失败 ");
dw = GetLastError();
printf("GetLastError-->%u/n", dw);
ExitProcess(dw);
return -1;
}
if (ReadCMD(hRead1,result) < 0)
{
printf("ReadCMD 失败 ");
dw = GetLastError();
printf("GetLastError-->%u/n", dw);
ExitProcess(dw);
return -1;
}
printf("**********************************************/n");
printf("%s/n",result.c_str());
printf("**********************************************/n");
CloseCMD(hRead1,hWrite1,hRead2,hWrite2,hCmd);
return 0;
}
//很重要一点:需要在IDE中把编码设置成“多字节字符集(MBCS)”而不是UNICODE!为了这个我折腾了大半天。