a VC++ Class to redirect console output to a file
//class to redirect console output to a file, based on http://bdn.borland.com/article/0,1410,10387,00.html
#include <fstream>
#include <memory>
#include "atlaux2.h" //need to download it from internet
#include <sstream>
#include <process.h>
//Onega on Windows XP SP2, VC++ 8.0
typedef unsigned (__stdcall *start_address )( void * );
class RedirectProcess:public CAuxStdThunk<RedirectProcess>
{
public:
RedirectProcess( LPCTSTR application_name, LPCTSTR command_line):
m_application_name(application_name), m_command_line(command_line)
{
InitThunk( (TMFP)&RedirectProcess::thread_procedure,this);
}
~RedirectProcess()
{
OutputDebugString(__FUNCTION__);
}
unsigned __stdcall thread_procedure(void *p)
{
pipe_method1(m_application_name.c_str(), m_command_line.c_str());
std::basic_stringstream<TCHAR> ts;
ts<< _T("Process ID:") << getpid()
<<_T(" Thread id:")<<GetCurrentThreadId()
<<_T(", exe: ")<<m_application_name
<<_T(", command line:")<<m_command_line
<<_T(" sample made by Onega (www.fruitfruit.com) ");
OutputDebugString(ts.str().c_str());
ts.clear();
delete this;
return 0;
}
private:
std::basic_string<TCHAR> m_application_name;
std::basic_string<TCHAR> m_command_line;
void pipe_method1(LPCTSTR exe, LPCTSTR cmd_line)
{
std::ofstream log_file;
log_file.open("c:\\onega.txt");
//http://bdn.borland.com/article/0,1410,10387,00.html
int buf_length = 4096;
std::auto_ptr<TCHAR> buf(new TCHAR[buf_length+1]);
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd; //security information for pipes
PROCESS_INFORMATION pi;
HANDLE newstdin,newstdout,read_stdout,write_stdin; //pipe handles
//if (IsWinNT()) //initialize security descriptor (Windows NT)
{
InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
sa.lpSecurityDescriptor = &sd;
}
//else sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true; //allow inheritable handles
if (!CreatePipe(&newstdin,&write_stdin,&sa,0)) //create stdin pipe
{
log_file<< "CreatePipe failed, error code:"<<GetLastError()<< " at line "<< __LINE__;
return;
}
if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //create stdout pipe
{
log_file<< "CreatePipe failed, error code:"<<GetLastError()<< " at line "<< __LINE__;
CloseHandle(newstdin);
CloseHandle(write_stdin);
return;
}
GetStartupInfo(&si); //set startupinfo for the spawned process
/*
The dwFlags member tells CreateProcess how to make the process.
STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
validates the wShowWindow member.
*/
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdOutput = newstdout;
si.hStdError = newstdout; //set the new handles for the child process
si.hStdInput = newstdin;
//TCHAR app_spawn[] = _T("D:\\share\\test\\vc8\\console\\boost\\unittest\\test1\\Debug\\test1.exe"); //sample, modify for your
//spawn the child process
if (!CreateProcess(exe,(LPTSTR)cmd_line,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
NULL,NULL,&si,&pi))
{
log_file<< "CreateProcess failed, error code:"<<GetLastError()<< " at line "<< __LINE__;
//getch();
CloseHandle(newstdin);
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
return;
}
unsigned long exit=0; //process exit code
unsigned long bread; //bytes read
unsigned long avail; //bytes available
for(;;) //main program loop
{
GetExitCodeProcess(pi.hProcess,&exit); //while the process is running
if (exit != STILL_ACTIVE)
break;
PeekNamedPipe(read_stdout,buf.get() ,buf_length,&bread,&avail,NULL);
//check to see if there is any data to read from stdout
if (bread != 0)
{
if (avail > buf_length)
{
while (bread >= buf_length)
{
memset(buf.get(),0, buf_length + 1);
ReadFile(read_stdout,buf.get(),buf_length,&bread,NULL); //read the stdout pipe
log_file<< (LPCSTR)buf.get();
OutputDebugString((LPCSTR)buf.get());
}
}
else {
memset(buf.get(),0, buf_length + 1);
ReadFile(read_stdout,buf.get(),buf_length,&bread,NULL);
log_file<< (LPCSTR)buf.get();
OutputDebugString((LPCSTR)buf.get());
}
}
else
{
//must not call sleep, otherwise the code will fail to capture output
//Sleep(1);
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(newstdin); //clean stuff up
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
if(exe)
log_file<<exe;
if(cmd_line)
log_file<< cmd_line;
log_file<< " program closed "<<__FUNCTION__;
log_file.flush();
log_file.close();
}
};
//////usage
void Cpipe_cmd2Dlg::OnBnClickedOk()
{
CString exe, cmd_line;
GetDlgItemText(IDC_EDIT1, exe);
GetDlgItemText(IDC_EDIT2, cmd_line);
if(exe.GetLength()==0)
exe = "c:\\winnt\\system32\\ipconfig.exe";
//pipe_method1(exe, cmd_line);
RedirectProcess *ptr_thread;
ptr_thread = new RedirectProcess(exe,cmd_line);
HANDLE hthread = (HANDLE)_beginthreadex(NULL, 0, (start_address)ptr_thread->GetThunk(), 0, 0, 0);
DWORD dwret = WaitForSingleObject(hthread, 1000 * 60);
CloseHandle(hthread);
AfxMessageBox(_T("Program end"));
//OnOK();
}
0 Comments:
Post a Comment
<< Home