CSDN博客

img wbly0

从匿名管道谈重定向技术

发表于2004/9/24 13:26:00  3019人阅读

分类: 匿名管道

                                 匿名管道与重定向技术
 正文
    首先我们得理解一个定义:重定向
何谓重定向?可以先字面理解为:重新决定方向!在控制台程序中,将标准的输入、输出句柄用管道的读、写句柄替换,而控制台程序本身并不知道它的输入、输出句柄已发生了变化,它依然将相关句柄(实为管道的读写句柄)作为标准的输入、输出句柄来看待。当父进程和子进程进行数据通信时的情形是这样的:父进程将标准的输出端重定向匿名管道的写句柄,启动子进程,因为继承关系,子进程也具有了这一特点,它的标准输出也与管道的写句柄联系在一起了。此时的父进程在关闭管道写句柄之后(一定要关闭),就可以通过读句柄来取得子进程发出的数据了。
   为了说明这个实事,我小举一例子,说明如何在图形界面中调用控制台的标准输出。程序运行的结果如下图:

程序按如下步骤实现:

1、新建一对话框CMyGUIDlg, 再加入一编辑框,设置好编辑框的属性(多行,水平&&垂直滚动条,自滚动,want return)ID号为:IDC_EDIT1
在ClassWizard中为IDC_EDIT1加入一CEdit型变量。

CEdit m_edit1;

2、加入一工作线程,函数可以为全局,当然也可以作为static型的类成员。我们选择后者。
   static UINT TestThread(LPVOID p);

3、在OnOK()消息处理函数中,加入如下代码:

void CMyGUIDlg::OnOK()
{

    AfxBeginThread(TestThread, this);
    UpdateData(TRUE);
}

4、在线程函数我们加入如下代码:
UINT CMyDUIDlg::TestThread(LPVOID p)
{
 STARTUPINFO si;
 PROCESS_INFORMATION pi;
 // 管道读句柄
 HANDLE hRead;
 // 管道写句柄
 HANDLE hWrite;
 
 SECURITY_ATTRIBUTES saAttr;
 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
 saAttr.lpSecurityDescriptor = 0;
 saAttr.bInheritHandle = true;
 
 // 创建匿名管道
 if(!CreatePipe(&hRead, &hWrite, &saAttr, 0))
 {
  AfxMessageBox("创建管道失败!");
  return 0;
 }
  // 得到本进程的当前标准输出
  // HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
 
  // 设置标准输出到匿名管道
  // SetStdHandle(STD_OUTPUT_HANDLE, hWrite);
 
 si.cb = sizeof(STARTUPINFO);
 GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息
 si.hStdError = hWrite;
 si.hStdOutput = hWrite;
 si.wShowWindow = SW_HIDE;
 si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // 让子进程隐藏、标准输出生效
 
 CString strLine;
 strLine.Format("cl -h %d /?", (unsigned int)hWrite); // 命令行参数
// 创建子进程
 if (!CreateProcess(NULL, (LPSTR)(LPCTSTR)strLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
 {
    AfxMessageBox("创建子进程失败!");
    return 0;
 }
 
 // 恢复本进程的标准输出
 // SetStdHandle(STD_OUTPUT_HANDLE, hTemp);

 CloseHandle(hWrite);   // 关闭写句柄(一定要关闭)
 CString strOut;
 char ReadBuf[100] = {0};
 DWORD dwRead;
 // 读管道直至管道关闭
 while (ReadFile(hRead, ReadBuf,99, &dwRead, NULL))
 {
  strOut += ReadBuf;
  memset(ReadBuf, 0, 99); 
 }
 CMyDUIDlg* plg = (CMyDUIDlg*)p;
 plg->m_edit1.SetWindowText(strOut);
 plg->InvalidateRect(NULL);

 CloseHandle(hRead);
 
 return 0;
}


作如下说明:
 1、本程序调用的控制台输出是VC++中的cl.exe运行的结果。当然你也可以自己加入一些控制台的 测试程序,将strLine赋值你想测试的控制台程序名即可。
 2、此程序在XP+VC6中测试通过。

阅读全文
0 0

相关文章推荐

img
取 消
img