您的位置:首页 > 其它

Windows管道与StdIn、StdOut重定向

2014-09-25 09:44 483 查看
       stdin是标准输入,stdout是标准输出,stderr是标准错误输出。大多数的命令行程序从stdin输入,输出到stdout或stderr,有时我们需要重定向stdout,stderr,stdin。比如:将输出写入文件,又或者我们要将命令行程序输出结果显示到Windows对话框中。

      在Windows编程中,重定向需要用到管道(Pipe)的概念。管道是一种用于在进程间共享数据的机制。一个管道类似于一个管子的两端,一端是写入的,一端是读出的。由一个进程从写入端写入、另一个进程从读出端读出,从而实现通信,就向一个“管道”一样。

重定向的原理是:

首先声明两个概念:主程序(重定向的操纵者)、子进程(被重定向的子进程)

如果要重定向stdout的话,先生成一个管道, 管道的写入端交给子进程去写,主程序从管道的读出端读数据,然后可以把数据写成文件、显示等等。重定向stderr和stdout是相同的。

同理,要重定向stdin的话,生成一个管道, 管道的写入端由主程序写,子进程从管道的读出端读数据。

下面是一个输出重定向的例子:将一个命令行Ping的结果展示在编辑框里。





核心代码如下:

#define MSG_DATAREC WM_USER +0x400

BEGIN_MESSAGE_MAP(CStudyStdOut_RedirectGuiDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, &CStudyStdOut_RedirectGuiDlg::OnBnClickedButton1)
ON_MESSAGE(MSG_DATAREC,&CStudyStdOut_RedirectGuiDlg::OnDataRec)
END_MESSAGE_MAP()

void CStudyStdOut_RedirectGuiDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa,sizeof(sa));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //默认的安全描述符
sa.bInheritHandle = TRUE; //这个必须要设定TRUE,参考资料:《windows核心编程》第三章
HANDLE hRead, hWrite;

if( !CreatePipe(&hRead, &hWrite, &sa, 0) )
{
MessageBox(" CreatePipe return FALSE.");
return;
}

m_hReadPipe = hRead;
AfxBeginThread(ReadPipeProc,this,NULL);

STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcInfo;
ZeroMemory(&siStartInfo,sizeof(STARTUPINFO));
siStartInfo.cb =sizeof(STARTUPINFO);
siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
siStartInfo.hStdOutput = hWrite;
siStartInfo.hStdError = hWrite;

TCHAR szCmdPar[256] = "ping www.baidu.com";
if(!CreateProcess(NULL, szCmdPar,NULL,NULL,TRUE,NULL,NULL,NULL,&siStartInfo, &piProcInfo))
{
MessageBox("CreateProcess failed!");
return;
}

CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);

}

UINT ReadPipeProc( LPVOID pParam )
{
CStudyStdOut_RedirectGuiDlg * pAttachWnd = static_cast<CStudyStdOut_RedirectGuiDlg *>(pParam);
HANDLE hRead = pAttachWnd->m_hReadPipe;
HWND hWnd = pAttachWnd->GetSafeHwnd();

DWORD bytesRead;
while( 1 )
{
int len = sizeof(pAttachWnd->m_szData);
ZeroMemory(&pAttachWnd->m_szData,len);

if( !ReadFile(hRead, pAttachWnd->m_szData, len-1, &bytesRead, NULL) )
break;

SendMessage(hWnd,MSG_DATAREC,0,0);
}

return 0;
}
HRESULT CStudyStdOut_RedirectGuiDlg::OnDataRec( WPARAM wParam, LPARAM lParam )
{
m_strEdit += m_szData;
UpdateData(FALSE);
return 1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息