vc6.0 异步输出cmd打印

预备知识:

SECURITY_ATTRIBUTES
结构包含一个 对象 的安全描述符,并指定 检索 到指定这个 结构 的句柄是否是可继承的。这种结构提供了安全设置的CreateFile,CREATEPIPE,CreateProcess的,RegCreateKeyEx的,或RegSaveKeyEx 各种功能,如创建的对象。
typedef的结构_SECURITY_ATTRIBUTES {
DWORD nLength; / /结构体的大小,可用SIZEOF取得
LPVOID lpSecurityDescriptor; / / 安全描述符
BOOL bInheritHandle ;/ /安全描述的对象能否被新创建ÆÆ的进程继承
} SECURITY_ATTRIBUTES,* PSECURITY_ATTRIBUTES;
STARTUPINFO结构 该结构用于指定新进程的主窗口特性
PROCESS_INFORMATION 结构
在创建进程时相关的 数据结构之一,该结构返回有关新进程及其 主线程的信息。其结构定义如下。
typedef struct_PROCESS_INFORMATION{
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
}PROCESS_INFORMATION;
其中成员含义如下。
① hProcess:返回新进程的句柄。
② hThread:返回 主线程的句柄。
③ dwProcessId:返回一个全局进程 标识符。该 标识符用于标识一个进程。从进程被
创建到终止,该值始终有效。
④ dwThreadId:返回一个全局线程 标识符。该 标识符用于标识一个线程。从 线程被创
建到终止,该值始终有效。
CreateProcess()
WIN32API函数CreateProcess用来创建一个新的进程和它的 主线程,这个新进程运行指定的 可执行文件
readFile()
此处使用readFile()读取管道;管道不支持异步读写,所以在读的时候经常会卡在readFile()这里,readFile()返回条件:
The ReadFile function returns when one of the following conditions occur:


A write operation completes on the write end of the pipe.
The number of bytes requested is read.
An error occurs.

所以采用创建子线程读取管道内容,避免主线程卡死;
 
GetExitCodeProcess()
BOOL WINAPI GetExitCodeProcess(
__in HANDLE hProcess,
__out LPDWORD lpExitCode
);
获取一个已中断进程的退出代码
返回值:
Long,非零表示成功,零表示失败。会设置GetLastError
参数表:
hProcess Long,想获取退出代码的一个进程的句柄
lpExitCode Long,用于装载进程退出代码的一个长整数 变量。如进程尚未中止,则设为常数STILL_ACTIVE
 
 

管道:

  管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

  匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:

BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针
 PHANDLE hWritePipe, // 指向写句柄的指针
 LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针
 DWORD nSize // 管道大小
);

原文地址:http://blog.csdn.net/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();
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值