管 道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另 一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。
BOOL WINAPI CreatePipe(
_Out_ PHANDLE hReadPipe,
_Out_ PHANDLE hWritePipe,
_In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,
_In_ DWORD nSize
);
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
方法一:创建一个pipe然后是cmd执行的结果输出到pipe里,然后再读取,这里遇到一个问题就是在hInput 这个witepipe写完之后得关闭,使write 结束,这样之后的readfile才可以执行而不被阻塞;
int ReadCmdContextOne()
{
STARTUPINFO st ;
PROCESS_INFORMATION pi;
HANDLE hOutPut,hInPut;
SECURITY_ATTRIBUTES sa;
DWORD readByte = 0;
int len = 0;
BOOL hResult ;
char buffer[4096];
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle =TRUE;
sa.lpSecurityDescriptor = NULL;
if(!CreatePipe(&hOutPut,&hInPut,&sa,0))
{
cout<<"create pipe failed erorr="<<GetLastError()<<endl;
return 1;
}
st.cb = sizeof(STARTUPINFO);
GetStartupInfo(&st);
st.hStdOutput = hInPut;
st.hStdError = hInPut;
st.wShowWindow = SW_HIDE;
st.dwFlags = STARTF_USESHOWWINDOW |STARTF_USESTDHANDLES;
if(!CreateProcess(NULL,"c:\\windows\\system32\\cmd.exe /c ipconfig /all",NULL,
NULL,TRUE,NULL,NULL,NULL,&st,&pi))
{
cout<<"failed create proccess,error="<<GetLastError()<<endl;
return 1;
}
DWORD dwRet = WaitForSingleObject(pi.hProcess,INFINITE);
switch(dwRet)
{
case WAIT_TIMEOUT:
case WAIT_FAILED:
return 1;
case WAIT_OBJECT_0:
CloseHandle(hInPut);//close hInPut handle ,make hte write pipe completes
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
memset(buffer,0,sizeof(buffer));
do
{
//a write operation completes on the write end of the pipe,so ReadFile can begin
hResult = ReadFile(hOutPut,buffer+len,1024,&readByte,NULL);
len += readByte;
Sleep(200);
}
while(readByte!=0 && hResult);
cout<<buffer<<endl;
CloseHandle(hOutPut);
return 0;
}
方法二:
就是执行命令的时候加一个输出重定向到文件,然后再从文件中读取;文件最好建一个临时文件,不过windows还是不会帮我们自动删除的,需要我们自己删除;
void exec()
{
HANDLE hFile;
STARTUPINFO st = {sizeof(STARTUPINFO)} ;
PROCESS_INFORMATION pi;
char szTempPath[MAX_PATH];
char szTempFile[MAX_PATH];
char buffer[4096];
char cmdLine[100];
DWORD dwRet ;
DWORD dwReadByte;
dwRet = GetTempPath(MAX_PATH,szTempPath);
if(!SUCCEEDED(dwRet))
{
cout<<"failed to Get temp path"<<GetLastError()<<endl;
return 1;
}
dwRet = GetTempFileName(szTempPath,TEXT("JJJJJay.txt"),0,szTempFile);
if(!SUCCEEDED(dwRet))
{
cout<<"failed to create temp file"<<GetLastError()<<endl;
return 1;
}
memset(cmdLine,0,sizeof(cmdLine));
int strLen = sizeof("c:\\windows\\system32\\cmd.exe /c ipconfig /all >");
memcpy(cmdLine,"c:\\windows\\system32\\cmd.exe /c ipconfig /all >",strLen);
memcpy(cmdLine+strLen-1,szTempFile,sizeof(szTempFile));
cmdLine[strLen+sizeof(szTempFile)] = '\0';
cout<<cmdLine<<endl;
if(!CreateProcess(NULL,cmdLine,NULL,
NULL,TRUE,NULL,NULL,NULL,&st,&pi))
{
cout<<"failed create proccess,error="<<GetLastError()<<endl;
return 1;
}
dwRet = WaitForSingleObject(pi.hProcess,INFINITE);
switch(dwRet)
{
case WAIT_TIMEOUT:
case WAIT_FAILED:
return 1;
case WAIT_OBJECT_0:
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
hFile = CreateFile(szTempFile,GENERIC_READ,FILE_SHARE_DELETE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(hFile == INVALID_HANDLE_VALUE)
{
cout<<"failed to create file"<<GetLastError()<<endl;
return 0;
}
memset(buffer,0,sizeof(buffer));
int len = 0 ;
do
{
dwRet = ReadFile(hFile,buffer+len,1024,&dwReadByte,NULL);
len += dwRet;
}while(dwRet && dwReadByte!=0);
CloseHandle(hFile);
DeleteFile(szTempFile);
return 0;
}