CreateProcess Redirect Pipe

Posted 卡尔特人头狼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ([email protected])
// 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 ([email protected]) for providing the essential
// code for this class.
//
// Thanks to Chris Maunder ([email protected]) 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] = ‘\0‘;

//------------------------------------------------------------------
// Replace backspaces with spaces.
//------------------------------------------------------------------
for ( DWORD ii = 0; ii < NumBytesRead; ii++ )
{
if ( PipeData[ii] == _T(‘\b‘) )
{
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 = ‘\0‘;
}

//------------------------------------------------------------------
// 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("\r\nCancelled.\r\n\r\nProcess terminated successfully.\r\n"));
}
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("\r\n");
if ( Success )
{
Msg += LPTSTR(lpMsgBuf);
}
else
{
Msg += _T("No status because FormatMessage failed.\r\n");
}

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();

以上是关于CreateProcess Redirect Pipe的主要内容,如果未能解决你的问题,请参考以下文章

CreateProcess函数回来的进程ID和任务管理器的不同

非常简单的利用CreateProcess注入DLL的方法

CreateProcess() 不适用于 lpCurrentDirectory

CreateProcess 命令行参数

CreateProcess() C++ 文件未找到

CreateProcess() 无法正常工作