实现原理:
管道是一种在进程间共享数据的机制,其实质是一段共享内存。Windows系统为这段共享的内存设计使用数据流I/O的方式来访问。一个进程读,另一个进程写,这类似于一个管道的两端,因此这种进程间的通信方式称为“管道”。管道分为匿名管道和命名管道。匿名管道只能在父子进程间进行通信,不能在网络间通信,而且数据传输是单向的,只能一端写,另一端读。命名管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时间只能有一端读、一端写。创建命名管道的方式可以获取CMD执行结果的输出内容
实现过程:
(1).调用函数CreatePipe创建匿名管道,获取管道数据读取句柄和管道数据写入句柄。
(2).创建新进程(进程属性为窗口隐藏、窗口的缓存句柄设置为上面得到的管道数据写入句柄)
(3).调用函数WaitForSingleObject等待命令执行完毕
(4).调用ReadFile函数根据匿名管道的数据读取句柄从匿名管道的缓冲区中读取数据
(5).关闭句柄,释放资源
实现代码:
//************************************ // 函数名:CCmdDlg::PipeCmd // 返回类型:BOOL // 功能: 执行CMD命令, 并获取执行结果数据 // 参数1:char *pszCmd cmd命令 // 参数2:char *pszResultBuffer 接收CMD结果的缓冲区 // 参数3:DWORD dwResultBufferSize 缓冲区大小(缓冲区要大点,不然接收到的结果不全) //************************************ BOOL CCmdDlg::PipeCmd(char *pszCmd, char *pszResultBuffer, DWORD dwResultBufferSize) { SECURITY_ATTRIBUTES securityAttributes = { 0 }; // 设定管道的安全属性 securityAttributes.bInheritHandle = TRUE; securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; // 创建匿名管道 HANDLE hReadPipe = NULL; HANDLE hWritePipe = NULL; BOOL bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0); if (FALSE == bRet) { MessageBox(_T("CreatePipe Error")); return FALSE; } STARTUPINFO si = { 0 }; // 设置新进程参数 si.cb = sizeof(si); si.hStdError = hWritePipe; si.hStdOutput = hWritePipe; si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // 创建新进程执行命令, 将执行结果写入匿名管道中 PROCESS_INFORMATION pi = { 0 }; USES_CONVERSION; bRet = ::CreateProcess(NULL, A2W(pszCmd), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if (FALSE == bRet) { MessageBox(_T("CreateProcess Error")); } // 等待命令执行结束 ::WaitForSingleObject(pi.hThread, INFINITE); ::WaitForSingleObject(pi.hProcess, INFINITE); // 从匿名管道中读取结果到输出缓冲区 ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize); ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, NULL, NULL); // 关闭句柄, 释放内存 ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); ::CloseHandle(hWritePipe); ::CloseHandle(hReadPipe); return TRUE; }