본문 바로가기

Windows/MFC

콘솔프로그램 실행 및 결과 갈무리

외부이 글을 정리된 것들을 수정없이 게시하였습니다.
저작권에 문제가 있으시면 삭제 요청을 해 주시기 바랍니다.

1번 예제와 2번 예제 2가지가 있습니다.
필요하신 분들은 적절히 참고하여 사용하시면 되리라 생각합니다.
저도 적절히 사용하고 있습니다.


1. Example1

출처: http://blog.daum.net/aswip/7987517


다음 내용은 실행된 콘솔 프로그램의 출력 결과물을 갈무리 하는 방법에 대해서 설명하고 있습니다.

(※ 참고로 이와 같은 방법을 종종 "Console redirection" 이라고 말하기도 합니다.)

==> 유닉 버전 소스 위치 : http://blog.daum.net/aswip/8020595

#include <windows.h>
#include <stdio.h>

#define APP "C:\\Windows\\system32\\ipconfig.exe"

int main(int argc, char **argv)
{
    char szBuff[256];
    DWORD dwRead = 0, dwOut = 0, dwErr = 0;
    HANDLE hStdOutWrite = NULL, hStdOutRead = NULL;
    HANDLE hStdErrWrite = NULL, hStdErrRead = NULL;
    STARTUPINFO si;
    SECURITY_ATTRIBUTES sa;
    PROCESS_INFORMATION pi;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    CreatePipe(&hStdOutRead, &hStdOutWrite, &sa, 0);  /* 실행될 콘솔 프로그램에 넘길 stdout */
    CreatePipe(&hStdErrRead, &hStdErrWrite, &sa, 0);  /* 실행될 콘솔 프로그램에 넘길 stderr */

    ZeroMemory(&si,sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdOutput = hStdOutWrite;
    si.hStdInput  = NULL;
    si.hStdError  = hStdErrWrite;
    si.wShowWindow = SW_HIDE;       /* 눈에 보이지 않는 상태로 프로세스 시작 */

    CreateProcess(NULL,APP, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    CloseHandle(pi.hThread);

    while ( PeekNamedPipe(hStdOutRead, NULL, 0, NULL, &dwOut, NULL) || 
            PeekNamedPipe(hStdErrRead, NULL, 0, NULL, &dwErr, NULL) )  /* 읽어들일 데이터가 있는가? */
    { 
        if ( dwOut <= 0 && dwErr <= 0 && WaitForSingleObject(pi.hProcess, 0) != WAIT_TIMEOUT )
            break;  /* 실행되어진 콘솔 응용프로그램이 종료된 경우 */

        while ( PeekNamedPipe(hStdOutRead, NULL, 0, NULL, &dwOut, NULL) && dwOut > 0 )
        {
            ReadFile(hStdOutRead, szBuff, sizeof(szBuff), &dwRead,NULL);
            szBuff[dwRead] = 0;
            printf("%s", szBuff);
        }

        while ( PeekNamedPipe(hStdErrRead, NULL, 0, NULL, &dwErr, NULL) && dwErr > 0 )
        {
            ReadFile(hStdErrRead, szBuff, sizeof(szBuff), &dwRead,NULL);
            szBuff[dwRead] = 0;
            printf("%s", szBuff);
        }
    }

    CloseHandle(pi.hProcess);
    CloseHandle(hStdOutRead);
    CloseHandle(hStdOutWrite);
    CloseHandle(hStdErrRead);
    CloseHandle(hStdErrWrite);

    return 0;
}



2. Example 2

출처:http://www.codeproject.com/Articles/10134/Execute-a-Console-Application-From-VC

Introduction

To Execute a Console Application From VC++ and retrieve the messages shown in the console.

In many situations we may need to execute a console application or a DOS application from within our MFC application. ShellExcecute can be used for this purpose, but can only be used to run the application. Messages shown in the console is not reachable. In such cases the following procedure can help.

Here we create a read write pipe (two separate pipes, one for reading and one for writing).

Then we use CreateProcess to execute the process. Createprocess must be supplied with pointers to variables of STARTUPINFO andPROCESS_INFORMATION structures.

The pipes created are assigned to STARTUPINFO structure before it is passed to the CreateProcess function.

The CreateProcess function is used to run a new program.

CreateProcess( 
        LPCWSTR lpszImageName, 
        LPCWSTR lpszCmdLine, 
        LPSECURITY_ATTRIBUTES lpsaProcess, 
        LPSECURITY_ATTRIBUTES lpsaThread, 
        BOOL fInheritHandles, 
        DWORD fdwCreate, 
        LPVOID lpvEnvironment, 
        LPWSTR lpszCurDir, 
        LPSTARTUPINFOW lpsiStartInfo, 
        LPPROCESS_INFORMATION lppiProcInfo);
  • lpszImageName

    Pointer to a null-terminated string that specifies the module to execute.

  • lpszCmdLine

    Pointer to a null-terminated string that specifies the command line to execute. The system adds a null character to the command line, trimming the string if necessary, to indicate which file was actually used.

The function ExecuteExternalFile, takes two arguments:

  1. the application to be executed.
  2. the arguments.

It executes the application and returns the messages that are printed into the console as a CString.

CString ExecuteExternalFile(CString csExeName, CString csArguments)
{
  CString csExecute;
  csExecute=csExeName + " " + csArguments;
  
  SECURITY_ATTRIBUTES secattr; 
  ZeroMemory(&secattr,sizeof(secattr));
  secattr.nLength = sizeof(secattr);
  secattr.bInheritHandle = TRUE;

  HANDLE rPipe, wPipe;

  //Create pipes to write and read data
  CreatePipe(&rPipe,&wPipe,&secattr,0);
  //
  STARTUPINFO sInfo; 
  ZeroMemory(&sInfo,sizeof(sInfo));
  PROCESS_INFORMATION pInfo; 
  ZeroMemory(&pInfo,sizeof(pInfo));
  sInfo.cb=sizeof(sInfo);
  sInfo.dwFlags=STARTF_USESTDHANDLES;
  sInfo.hStdInput=NULL; 
  sInfo.hStdOutput=wPipe; 
  sInfo.hStdError=wPipe;
  char command[1024]; strcpy(command,  
          csExecute.GetBuffer(csExecute.GetLength()));

  //Create the process here.
  CreateProcess(0 command,0,0,TRUE,
          NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
  CloseHandle(wPipe);

  //now read the output pipe here.
  char buf[100];
  DWORD reDword; 
  CString m_csOutput,csTemp;
  BOOL res;
  do
  {
                  res=::ReadFile(rPipe,buf,100,&reDword,0);
                  csTemp=buf;
                  m_csOutput+=csTemp.Left(reDword);
  }while(res);
  return m_csOutput;
}

Hope this code will be useful for you.