Redirecting an arbitrary Console's Input/Output

#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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章