添加 'SubProcessIO.cpp'
This commit is contained in:
parent
e576d13a4f
commit
e6045d5d06
276
SubProcessIO.cpp
Normal file
276
SubProcessIO.cpp
Normal file
|
@ -0,0 +1,276 @@
|
|||
#include "SubProcessIO.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
struct SubProcessIO::_impl
|
||||
{
|
||||
HANDLE ghChildStdInRead;
|
||||
HANDLE ghChildStdInWrite;
|
||||
HANDLE ghChildStdOutRead;
|
||||
HANDLE ghChildStdOutWrite;
|
||||
|
||||
HANDLE hChildProcess;
|
||||
|
||||
bool flagDetach;
|
||||
bool flagStopped;
|
||||
bool flagTerminateOnDestruct;
|
||||
};
|
||||
|
||||
SubProcessIO::SubProcessIO(const std::string& Command,bool TerminateOnDestruct) throw(std::runtime_error)
|
||||
{
|
||||
_pimpl=new _impl;
|
||||
_pimpl->ghChildStdInRead=NULL;
|
||||
_pimpl->ghChildStdInWrite=NULL;
|
||||
_pimpl->ghChildStdOutRead=NULL;
|
||||
_pimpl->ghChildStdOutWrite=NULL;
|
||||
_pimpl->flagDetach=false;
|
||||
_pimpl->flagStopped=true;
|
||||
_pimpl->flagTerminateOnDestruct=TerminateOnDestruct;
|
||||
|
||||
int ret;
|
||||
if((ret=createSubProcessWith(Command))<0)
|
||||
{
|
||||
char buff[128];
|
||||
memset(buff,0,128);
|
||||
snprintf(buff,0,"Error on createSubProcessWith(...), ReturnVal: %d",ret);
|
||||
throw std::runtime_error(buff);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pimpl->flagStopped=false;
|
||||
}
|
||||
}
|
||||
|
||||
SubProcessIO::~SubProcessIO()
|
||||
{
|
||||
if(!_pimpl->flagStopped)
|
||||
{
|
||||
/// Process is running
|
||||
if(!_pimpl->flagDetach)
|
||||
{
|
||||
/// Process not detached...
|
||||
if(_pimpl->flagTerminateOnDestruct)
|
||||
{
|
||||
/// Terminate Flag is set. Then call terminate!
|
||||
terminate();
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Terminate Flag is not set. Then wait the child process to exit.
|
||||
wait();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Process is detached. Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
/// Close I/O Handle.
|
||||
CloseHandle(_pimpl->ghChildStdInWrite);
|
||||
CloseHandle(_pimpl->ghChildStdOutRead);
|
||||
|
||||
/// Close Child Process Handle.
|
||||
CloseHandle(_pimpl->hChildProcess);
|
||||
|
||||
delete _pimpl;
|
||||
}
|
||||
|
||||
// protected
|
||||
int SubProcessIO::createSubProcessWith(const std::string& Command)
|
||||
{
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
saAttr.nLength=sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle=TRUE;
|
||||
saAttr.lpSecurityDescriptor=NULL;
|
||||
|
||||
if( ! CreatePipe(&(_pimpl->ghChildStdOutRead),&(_pimpl->ghChildStdOutWrite),&saAttr,0))
|
||||
{
|
||||
printf("Error on Create Pipe.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( ! SetHandleInformation(_pimpl->ghChildStdOutRead,HANDLE_FLAG_INHERIT,0) )
|
||||
{
|
||||
printf("Error on SetHandleInformation.\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if( ! CreatePipe(&(_pimpl->ghChildStdInRead),&(_pimpl->ghChildStdInWrite),&saAttr,0))
|
||||
{
|
||||
printf("Error on Create Another Pipe.\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if( ! SetHandleInformation(_pimpl->ghChildStdInWrite,HANDLE_FLAG_INHERIT,0))
|
||||
{
|
||||
printf("Error on another SetHandleInformation.\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
/// Create SubProcess.
|
||||
PROCESS_INFORMATION procInfo;
|
||||
STARTUPINFO startInfo;
|
||||
BOOL bSuccess=FALSE;
|
||||
|
||||
ZeroMemory(&procInfo,sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&startInfo,sizeof(STARTUPINFO));
|
||||
|
||||
startInfo.cb=sizeof(STARTUPINFO);
|
||||
startInfo.hStdError=_pimpl->ghChildStdOutWrite;
|
||||
startInfo.hStdOutput=_pimpl->ghChildStdOutWrite;
|
||||
startInfo.hStdInput=_pimpl->ghChildStdInRead;
|
||||
startInfo.dwFlags|=STARTF_USESTDHANDLES;
|
||||
|
||||
/// Create Child Process (Real Call)
|
||||
bSuccess=CreateProcess(NULL,(char*)Command.c_str(),
|
||||
NULL, /// security attribute
|
||||
NULL, /// primary thread attribute
|
||||
TRUE, /// inherit handles
|
||||
0, /// creation flag
|
||||
NULL, /// use parent's environment
|
||||
NULL, /// use parent's current directory
|
||||
&startInfo, /// Use this start info
|
||||
&procInfo /// Use this process info
|
||||
);
|
||||
|
||||
if(!bSuccess)
|
||||
{
|
||||
printf("Failed on CreateProcess.\n");
|
||||
return -5;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Close Thread Handle.
|
||||
CloseHandle(procInfo.hThread);
|
||||
//CloseHandle(procInfo.hProcess);
|
||||
|
||||
_pimpl->hChildProcess=procInfo.hProcess;
|
||||
|
||||
/// Close Not Used Handle in father process.
|
||||
CloseHandle(_pimpl->ghChildStdOutWrite);
|
||||
CloseHandle(_pimpl->ghChildStdInRead);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SubProcessIO::writeToSubProcess(const char* buffer,int szToWrite)
|
||||
{
|
||||
if(szToWrite<=0) return -1;
|
||||
|
||||
DWORD dwWritten,dwDone,dwAll;
|
||||
dwDone=0;
|
||||
dwAll=szToWrite;
|
||||
while(dwDone<dwAll)
|
||||
{
|
||||
dwWritten=0;
|
||||
BOOL bSuccess=WriteFile(_pimpl->ghChildStdInWrite,buffer+dwDone,dwAll-dwDone,&dwWritten,NULL);
|
||||
if(!bSuccess)
|
||||
{
|
||||
/// Error on WriteFile
|
||||
return -2;
|
||||
}
|
||||
dwDone+=dwWritten;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SubProcessIO::peekSubProcess()
|
||||
{
|
||||
DWORD available;
|
||||
if(!PeekNamedPipe(_pimpl->ghChildStdOutRead,NULL,0,NULL,&available,NULL))
|
||||
{
|
||||
printf("Failed to peek named pipe.\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return available;
|
||||
}
|
||||
}
|
||||
|
||||
int SubProcessIO::readFromSubProcess(char* buffer,int szToRead)
|
||||
{
|
||||
if(szToRead<=0) return -1;
|
||||
|
||||
DWORD dwRead,dwDone,dwAll;
|
||||
dwDone=0;
|
||||
dwAll=szToRead;
|
||||
|
||||
while(dwDone<dwAll)
|
||||
{
|
||||
BOOL bSuccess=ReadFile(_pimpl->ghChildStdOutRead,buffer+dwDone,dwAll-dwDone,&dwRead,NULL);
|
||||
if(!bSuccess)
|
||||
{
|
||||
/// Read Error.
|
||||
return -2;
|
||||
}
|
||||
dwDone+=dwRead;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SubProcessIO::wait()
|
||||
{
|
||||
DWORD ret=WaitForSingleObject(_pimpl->hChildProcess,INFINITE);
|
||||
switch(ret)
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
return -1;
|
||||
case WAIT_OBJECT_0:
|
||||
return 0;
|
||||
case WAIT_TIMEOUT:
|
||||
return -2;
|
||||
case WAIT_FAILED:
|
||||
return -3;
|
||||
}
|
||||
return -4;
|
||||
}
|
||||
|
||||
int SubProcessIO::wait(int ms)
|
||||
{
|
||||
DWORD ret=WaitForSingleObject(_pimpl->hChildProcess,ms);
|
||||
switch(ret)
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
return -1;
|
||||
case WAIT_OBJECT_0:
|
||||
return 0;
|
||||
case WAIT_TIMEOUT:
|
||||
return -2;
|
||||
case WAIT_FAILED:
|
||||
return -3;
|
||||
}
|
||||
return -4;
|
||||
}
|
||||
|
||||
int SubProcessIO::getExitCode()
|
||||
{
|
||||
DWORD code;
|
||||
GetExitCodeProcess(_pimpl->hChildProcess,&code);
|
||||
return code;
|
||||
}
|
||||
|
||||
int SubProcessIO::terminate()
|
||||
{
|
||||
BOOL ret=TerminateProcess(_pimpl->hChildProcess,0);
|
||||
if(ret!=FALSE)
|
||||
{
|
||||
/// Terminate Successfully.
|
||||
_pimpl->flagStopped=true;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Terminate Error.
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void SubProcessIO::detach()
|
||||
{
|
||||
_pimpl->flagDetach=true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user