Onega

a lot of VC++ posts, a few C# posts, and some miscellaneous stuff

Monday, June 05, 2006

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