预备知识:
A write operation completes on the write end of the pipe.
The number of bytes requested is read.
An error occurs.
管道:
管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。
匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:
BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针
PHANDLE hWritePipe, // 指向写句柄的指针
LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针
DWORD nSize // 管道大小
);
原文地址:http://blog.youkuaiyun.com/zfmcmm/article/details/11895917
代码:
BOOL CTestItem::fnExecuetTask(CString &csTaskPath)
{
ACT_INTERRUPT
CString csErrorInfo;
CString csInfo;
SECURITY_ATTRIBUTES sa;
HANDLE hRead,hWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead,&hWrite,&sa,0))
{
csErrorInfo.Format("CreatePipe()错误\r\n");
OutputText(1,csErrorInfo,RGB(255,0,0));
return FALSE;
}
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
//创建子进程,在测试代码中子进程启动时会有两个进程cmd.exe 和(win7中)conhost.exe,后者应该是从父进程继承,csTaskPath是要执行的命令行.bat文件
if (!CreateProcess((LPSTR)(LPCTSTR)csTaskPath,NULL,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
{
csErrorInfo.Format("CreateProcess()错误\r\n");
OutputText(1,csErrorInfo,RGB(255,0,0));
return FALSE;
}
//创建线程读取管道内容(管道不支持异步读写)
CONSOLE *paramEx = new CONSOLE;
paramEx->hRead = hRead;
paramEx->m_pPlatUI = this->m_pPlatUI;
HANDLE hThreadRead = (HANDLE)_beginthread(fnReadPipeThread,0,(void *)paramEx);
if (-1 == (int)hThreadRead)
{
csErrorInfo.Format("_beginthread()错误\r\n");
OutputText(1,csErrorInfo,RGB(255,0,0));
return FALSE;
}
DWORD dwExitCode;
while(TRUE)
{
//判断进程是否退出;
GetExitCodeProcess(pi.hProcess,&dwExitCode);
if (dwExitCode != STILL_ACTIVE)
{
break;
}
//如果测试中断
if(IsTestStop())
{
//结束进程
if (pi.hProcess)
{
GetExitCodeProcess(pi.hProcess,&dwExitCode);
if (!TerminateProcess(pi.hProcess,dwExitCode))//强制结束进程,在测试程序中,此处只能关闭cmd.exe不能关闭conhost.exe
{
csErrorInfo.Format("TerminateProcess()错误\r\n");
OutputText(1,csErrorInfo,RGB(255,0,0));
return FALSE;
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
//关闭子进程继承的控制台窗口(conhost.exe),通过设置si.wShowWindow = SW_SHOW能看到此窗口,通过Microsoft Spy++查看该窗口信息
HWND hwCmd;
hwCmd = FindWindow("ConsoleWindowClass","C:\\ATE\\Bin\\PlatForm.exe");//窗口标题在调试的时候和打包运行的时候不一样,所以在下面再关闭了一次
// str.Format("HWND1 ===== %d \r\n",(int)hwCmd);
// OutputText(1,str,RGB(255,0,0));
::SendMessage(hwCmd,WM_CLOSE,(WPARAM)0,(LPARAM)0);//使用TerminateProcess无法关闭
//获取系统版本号
OSVERSIONINFO osi;
ZeroMemory(&osi,sizeof(OSVERSIONINFO));
osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osi);
//判断系统是否是XP(区分在xp和WIN7)
if (osi.dwMinorVersion >= 1 && osi.dwMajorVersion == 5)
{
hwCmd = FindWindow("ConsoleWindowClass","C:\\Documents and Settings\\All Users\\桌面\\v3.lnk");
}
else
{
hwCmd = FindWindow("ConsoleWindowClass","C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\v3\\v3.lnk");
}
// str.Format("HWND2 ===== %d \r\n",(int)hwCmd);
// OutputText(1,str,RGB(255,0,0));
::SendMessage(hwCmd,WM_CLOSE,(WPARAM)0,(LPARAM)0);
}
break;
}
Sleep(100);
}
//结束线程
GetExitCodeThread(hThreadRead,&dwExitCode);
if (dwExitCode == STILL_ACTIVE)
{
if (!TerminateThread(hThreadRead,0))
{
csErrorInfo.Format("TerminateThread()错误\r\n");
OutputText(1,csErrorInfo,RGB(255,0,0));
return FALSE;
}
CloseHandle(hThreadRead);
}
CloseHandle(hRead);
CloseHandle(hWrite);
if (paramEx != NULL)
{
delete paramEx;
}
return TRUE;
}
//读取cmd打印信息线程
void __cdecl fnReadPipeThread(void *parm)
{
CString csInfo;
char buffer[1024] = {0};
DWORD bytesRead;
CONSOLE *sTransmit = (CONSOLE *)parm;
HANDLE hRead = sTransmit->hRead;
IDllPlatUI* m_pPlatUI =sTransmit->m_pPlatUI ;
// Attempt an asynchronous read operation.
//bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,
// &gOverlapped) ;
// If there was a problem, or if the asynchronous operation
// is still pending.
while(TRUE)
{
BOOL bResult = ReadFile(hRead,buffer,1023,&bytesRead, NULL);
bool bBreak = false;
if (!bResult)
{
// Deal with the error code.
switch ( GetLastError() )
{
case ERROR_HANDLE_EOF: //如果读取到结尾
{
// WCode to handle the end of the file
// during the call to ReadFile
bBreak = true;
break;
}
default:
break;
}
if( bBreak )
break;
} // end if
csInfo.Format("%s\r\n",buffer);
CString szColor;
szColor.Format("color=%d,%d,%d",GetRValue(1),GetGValue(0),GetBValue(0));
if (NULL == m_pPlatUI)
return ;
m_pPlatUI->OutputSet(1,szColor);
m_pPlatUI->Output(1,csInfo);
}
_endthread();
}