zoukankan      html  css  js  c++  java
  • CreateProcess Redirect Pipe

    #ifndef REDIRECT_H_INCLUDED__
    #define REDIRECT_H_INCLUDED__

    class CRedirect
    {
    public:

    //--------------------------------------------------------------------------
    // constructor
    //--------------------------------------------------------------------------
    CRedirect
    (
    LPCTSTR szCurrentDirectory = NULL
    );

    //--------------------------------------------------------------------------
    // destructor
    //--------------------------------------------------------------------------
    virtual ~CRedirect();

    //--------------------------------------------------------------------------
    // public member functions
    //--------------------------------------------------------------------------
    virtual void Run(LPCTSTR szCommand);
    virtual void Stop();
    virtual CString GetOutPutString(){ return m_sOutput; }

    protected:

    //--------------------------------------------------------------------------
    // member functions
    //--------------------------------------------------------------------------
    void AppendText(LPCTSTR Text);
    void PeekAndPump();
    void SetSleepInterval(DWORD dwMilliseconds);
    void ShowLastError(LPCTSTR szText);

    //--------------------------------------------------------------------------
    // member data
    //--------------------------------------------------------------------------
    bool m_bStopped;
    DWORD m_dwSleepMilliseconds;
    CString m_sOutput;
    LPCTSTR m_szCurrentDirectory;

    };

    #endif // REDIRECT_H_INCLUDED__

    //------------------------------------------------------------------------------
    // Redirect.cpp : implementation file
    //
    // Creates a child process that runs a user-specified command and redirects its
    // standard output and standard error to a CEdit control.
    //
    // Written by Matt Brunk (brunk@gorge.net)
    // Copyright (C) 1999 Matt Brunk
    // All rights reserved.
    //
    // This code may be used in compiled form in any way. This file may be
    // distributed by any means providing it is not sold for profit without
    // the written consent of the author, and providing that this notice and the
    // author's name is included in the distribution. If the compiled form of the
    // source code in this file is used in a commercial application, an e-mail to
    // the author would be appreciated.
    //
    // Thanks to Dima Shamroni (dima@abirnet.co.il) for providing the essential
    // code for this class.
    //
    // Thanks to Chris Maunder (chrismaunder@codeguru.com) for the PeekAndPump()
    // function (from his CProgressWnd class).
    //
    // Initial Release Feb 8, 1999
    //------------------------------------------------------------------------------


    #include "stdafx.h"
    #include <string.h>
    #include "Redirect.h"

    const int BUF_SIZE = 8192;

    CRedirect::CRedirect
    (
    LPCTSTR szCurrentDirectory
    )
    {
    m_bStopped = false;
    m_dwSleepMilliseconds = 100;
    m_szCurrentDirectory = szCurrentDirectory;
    }

    CRedirect::~CRedirect()
    {
    }

    void CRedirect::Run(LPCTSTR szCommand)
    {
    HANDLE PipeReadHandle;
    HANDLE PipeWriteHandle;
    PROCESS_INFORMATION ProcessInfo;
    SECURITY_ATTRIBUTES SecurityAttributes;
    STARTUPINFO StartupInfo;
    BOOL Success;

    //--------------------------------------------------------------------------
    // Zero the structures.
    //--------------------------------------------------------------------------
    ZeroMemory( &StartupInfo, sizeof( StartupInfo ));
    ZeroMemory( &ProcessInfo, sizeof( ProcessInfo ));
    ZeroMemory( &SecurityAttributes, sizeof( SecurityAttributes ));

    //--------------------------------------------------------------------------
    // Create a pipe for the child's STDOUT.
    //--------------------------------------------------------------------------
    SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
    SecurityAttributes.bInheritHandle = TRUE;
    SecurityAttributes.lpSecurityDescriptor = NULL;

    Success = CreatePipe
    (
    &PipeReadHandle, // address of variable for read handle
    &PipeWriteHandle, // address of variable for write handle
    &SecurityAttributes, // pointer to security attributes
    0 // number of bytes reserved for pipe (use default size)
    );

    if ( !Success )
    {
    ShowLastError(_T("Error creating pipe"));
    return;
    }

    //--------------------------------------------------------------------------
    // Set up members of STARTUPINFO structure.
    //--------------------------------------------------------------------------
    StartupInfo.cb = sizeof(STARTUPINFO);
    StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    StartupInfo.wShowWindow = SW_HIDE;
    StartupInfo.hStdOutput = PipeWriteHandle;
    StartupInfo.hStdError = PipeWriteHandle;

    //----------------------------------------------------------------------------
    // Create the child process.
    //----------------------------------------------------------------------------
    Success = CreateProcess
    (
    NULL, // pointer to name of executable module
    LPTSTR(szCommand), // command line
    NULL, // pointer to process security attributes
    NULL, // pointer to thread security attributes (use primary thread security attributes)
    TRUE, // inherit handles
    0, // creation flags
    NULL, // pointer to new environment block (use parent's)
    m_szCurrentDirectory, // pointer to current directory name
    &StartupInfo, // pointer to STARTUPINFO
    &ProcessInfo // pointer to PROCESS_INFORMATION
    );

    if ( !Success )
    {
    ShowLastError(_T("Error creating process"));
    return;
    }

    DWORD BytesLeftThisMessage = 0;
    DWORD NumBytesRead;
    TCHAR PipeData[BUF_SIZE];
    DWORD TotalBytesAvailable = 0;

    for ( ; ; )
    {
    NumBytesRead = 0;

    Success = PeekNamedPipe
    (
    PipeReadHandle, // handle to pipe to copy from
    PipeData, // pointer to data buffer
    1, // size, in bytes, of data buffer
    &NumBytesRead, // pointer to number of bytes read
    &TotalBytesAvailable, // pointer to total number of bytes available
    &BytesLeftThisMessage // pointer to unread bytes in this message
    );

    if ( !Success )
    {
    ShowLastError(_T("PeekNamedPipe fialed"));
    break;
    }

    if ( NumBytesRead )
    {
    Success = ReadFile
    (
    PipeReadHandle, // handle to pipe to copy from
    PipeData, // address of buffer that receives data
    BUF_SIZE - 1, // number of bytes to read
    &NumBytesRead, // address of number of bytes read
    NULL // address of structure for data for overlapped I/O
    );

    if ( !Success )
    {
    ShowLastError(_T("ReadFile fialed"));
    break;
    }

    //------------------------------------------------------------------
    // Zero-terminate the data.
    //------------------------------------------------------------------
    PipeData[NumBytesRead] = '';

    //------------------------------------------------------------------
    // Replace backspaces with spaces.
    //------------------------------------------------------------------
    for ( DWORD ii = 0; ii < NumBytesRead; ii++ )
    {
    if ( PipeData[ii] == _T('') )
    {
    PipeData[ii] = ' ';
    }
    }

    //------------------------------------------------------------------
    // If we're running a batch file that contains a pause command,
    // assume it is the last output from the batch file and remove it.
    //------------------------------------------------------------------
    TCHAR *ptr = _tcsstr(PipeData, _T("Press any key to continue . . ."));
    if ( ptr )
    {
    *ptr = '';
    }

    //------------------------------------------------------------------
    // Append the output to the CEdit control.
    //------------------------------------------------------------------
    AppendText(PipeData);

    //------------------------------------------------------------------
    // Peek and pump messages.
    //------------------------------------------------------------------
    PeekAndPump();
    }
    else
    {
    //------------------------------------------------------------------
    // If the child process has completed, break out.
    //------------------------------------------------------------------
    if ( WaitForSingleObject(ProcessInfo.hProcess, 0) == WAIT_OBJECT_0 ) //lint !e1924 (warning about C-style cast)
    {
    break;
    }

    //------------------------------------------------------------------
    // Peek and pump messages.
    //------------------------------------------------------------------
    PeekAndPump();

    //------------------------------------------------------------------
    // If the user cancelled the operation, terminate the process.
    //------------------------------------------------------------------
    if ( m_bStopped )
    {
    Success = TerminateProcess
    (
    ProcessInfo.hProcess,
    0
    );

    if ( Success )
    {
    AppendText(_T(" Cancelled. Process terminated successfully. "));
    }
    else
    {
    ShowLastError(_T("Error terminating process."));
    }

    break;
    }

    //------------------------------------------------------------------
    // Sleep.
    //------------------------------------------------------------------
    Sleep(m_dwSleepMilliseconds);
    }

    }

    //--------------------------------------------------------------------------
    // Close handles.
    //--------------------------------------------------------------------------
    Success = CloseHandle(ProcessInfo.hThread);
    if ( !Success )
    {
    ShowLastError(_T("Error closing thread handle."));
    }

    Success = CloseHandle(ProcessInfo.hProcess);
    if ( !Success )
    {
    ShowLastError(_T("Error closing process handle."));
    }

    Success = CloseHandle(PipeReadHandle);
    if ( !Success )
    {
    ShowLastError(_T("Error closing pipe read handle."));
    }

    Success = CloseHandle(PipeWriteHandle);
    if ( !Success )
    {
    ShowLastError(_T("Error closing pipe write handle."));
    }

    }


    void CRedirect::ShowLastError(LPCTSTR szText)
    {
    LPVOID lpMsgBuf;
    DWORD Success;

    //--------------------------------------------------------------------------
    // Get the system error message.
    //--------------------------------------------------------------------------
    Success = FormatMessage
    (
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //lint !e1924 (warning about C-style cast)
    LPTSTR(&lpMsgBuf),
    0,
    NULL
    );

    CString Msg;

    Msg = szText;
    Msg += _T(" ");
    if ( Success )
    {
    Msg += LPTSTR(lpMsgBuf);
    }
    else
    {
    Msg += _T("No status because FormatMessage failed. ");
    }

    AppendText(Msg);

    }

    void CRedirect::PeekAndPump()
    {
    MSG Msg;
    while (::PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE))
    {
    (void)AfxGetApp()->PumpMessage(); //lint !e1924 (warning about C-style cast)
    }
    }

    void CRedirect::Stop()
    {
    m_bStopped = true;
    }

    void CRedirect::AppendText(LPCTSTR Text)
    {
    m_sOutput = Text;
    }

    void CRedirect::SetSleepInterval(DWORD dwMilliseconds)
    {
    m_dwSleepMilliseconds = dwMilliseconds;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //Useage Example

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    CString command_line = _T("xxx.dat 或 xxx.exe");
    CRedirect * pRedirect = new CRedirect();
    pRedirect->Run((LPTSTR)(LPCTSTR)command_line);
    CString sOutput = pRedirect->GetOutPutString();

  • 相关阅读:
    [转] 分代垃圾回收的 新旧代引用问题(原标题:Back To Basics: Generational Garbage Collection)
    javascript中数组总结
    mybatis 与 反射
    mybatis 与 缓存
    mybatis 与 日志
    mybatis与 Exception
    mybatis 与 xml
    Redis -- 03 持久化
    Redis -- 02 配置文件解析
    【翻译】Crafting a Next-Gen Material Pipeline for The Order: 1886
  • 原文地址:https://www.cnblogs.com/waterair/p/7434699.html
Copyright © 2011-2022 走看看