#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <io.h> #include <fcntl.h> #include <iostream> #include <boost/thread/thread.hpp> #include <boost/bind.hpp> #include <boost/algorithm/algorithm.hpp> #include <boost/format.hpp> #include <boost/tokenizer.hpp> #include <boost/algorithm/string.hpp> #define STDIN_FILENO 0 /* file descriptor for stdin */ #define STDOUT_FILENO 1 /* file descriptor for stdout */ #define STDERR_FILENO 2 /* file descriptor for stderr */ class TestReDirectConsole { public: HANDLE m_hRead = 0; HANDLE m_hWrite = 0; std::tr1::shared_ptr<boost::thread> m_thread = 0; TestReDirectConsole() { } ~TestReDirectConsole() { CloseHandle(m_hRead); CloseHandle(m_hWrite); } void getSTDPrint() { DWORD ReadNum = 0; char ReadBuf[1024] = { 0 }; while (1) { memset(ReadBuf, 0, 1024); OVERLAPPED OVERLAPPED_; memset(&OVERLAPPED_, 0, sizeof(OVERLAPPED)); OVERLAPPED_.hEvent = CreateEvent(NULL, FALSE/*每次執行完自動有信號*/, TRUE, NULL); PeekNamedPipe(m_hRead, 0, 0, 0, &ReadNum, 0);//預先查看管道中是否還有字符 if (!ReadNum||!ReadFile(m_hRead, ReadBuf, 1024, &ReadNum, &OVERLAPPED_)) { continue; } if (ReadNum == 0 || ReadBuf[0] == 0) { continue; } this->appendLog(ReadBuf); } } void appendLog(const std::string& strLog) { } protected: private: }; int _tmain(int argc, _TCHAR* argv[]) { TestReDirectConsole TestReDirectConsole_; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; //創建管道的時候,如果CreatePipe的第三個參數lpPipeAttributes = NULL或者SECURITY_ATTRIBUTES.bInheritHandle = FALSE, //會導致新創建的CMD進程不能繼承管道HANDLE,所以導致ReadFile阻塞的問題. BOOL bRet = CreatePipe(&TestReDirectConsole_.m_hRead, &TestReDirectConsole_.m_hWrite, &sa, 0); // 創建匿名管道 int nOpenHandle = _open_osfhandle((intptr_t)TestReDirectConsole_.m_hWrite, _O_TEXT); FILE* fp = _fdopen(nOpenHandle, "w"); *stdout = *fp; *stderr = *fp; //SetStdHandle(STD_OUTPUT_HANDLE, TestReDirectConsole_.m_hWrite); _dup2(nOpenHandle, STDOUT_FILENO); _dup2(nOpenHandle, STDERR_FILENO);//複製 setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0);//設置沒有緩衝區 _COMMTIMEOUTS _COMMTIMEOUTS_; memset(&_COMMTIMEOUTS_, 0, sizeof(_COMMTIMEOUTS_));//設置超時讀取 SetCommTimeouts(TestReDirectConsole_.m_hWrite, &_COMMTIMEOUTS_); SetCommTimeouts(TestReDirectConsole_.m_hRead, &_COMMTIMEOUTS_); //決定C++標準streams(cin,cout,cerr...)是否與相應的C標準程序庫文件(stdin,stdout,stderr)同步,也就是是否使用相同的stream緩衝區,缺省情況是同步的 std::ios_base::sync_with_stdio(true); TestReDirectConsole_.m_thread.reset(new boost::thread(boost::bind(&TestReDirectConsole::getSTDPrint , &TestReDirectConsole_))); TestReDirectConsole_.m_thread->detach(); //TestReDirectConsole_.m_thread->join(); while (true) { //Sleep(1000); printf("dddd"); std::cout << std::endl; fflush(stdout); //std::cerr << "kdkdk \n"; } return 0; }