143 строки
4.1 KiB
C++
143 строки
4.1 KiB
C++
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <tchar.h>
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <Windows.h>
|
|
|
|
namespace util
|
|
{
|
|
class CProcess
|
|
{
|
|
PROCESS_INFORMATION pInfo;
|
|
STARTUPINFO sInfo;
|
|
public:
|
|
CProcess()
|
|
{
|
|
ZeroMemory(&this->pInfo, sizeof(this->pInfo));
|
|
ZeroMemory(&this->sInfo, sizeof(this->sInfo));
|
|
this->sInfo.cb = sizeof(this->sInfo);
|
|
this->sInfo.dwFlags = STARTF_USESTDHANDLES;
|
|
}
|
|
virtual ~CProcess()
|
|
{
|
|
}
|
|
public:
|
|
void ConnectStdInput(HANDLE hPipeStdin)
|
|
{
|
|
this->sInfo.hStdInput = hPipeStdin;
|
|
}
|
|
void ConnectStdOutput(HANDLE hPipeStdout)
|
|
{
|
|
this->sInfo.hStdOutput = hPipeStdout;
|
|
}
|
|
void ConnectStdError(HANDLE hPipeStderr)
|
|
{
|
|
this->sInfo.hStdError = hPipeStderr;
|
|
}
|
|
public:
|
|
bool Start(const std::wstring& szCommandLine, bool bNoWindow)
|
|
{
|
|
std::vector<wchar_t> convert(szCommandLine.begin(), szCommandLine.end());
|
|
convert.push_back(0);
|
|
LPTSTR lpCommandLine = convert.data();
|
|
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
|
|
if (bNoWindow == true)
|
|
dwCreationFlags |= CREATE_NO_WINDOW;
|
|
BOOL bResult = ::CreateProcess(nullptr,
|
|
lpCommandLine,
|
|
nullptr,
|
|
nullptr,
|
|
TRUE,
|
|
dwCreationFlags,
|
|
nullptr,
|
|
nullptr,
|
|
&this->sInfo,
|
|
&this->pInfo);
|
|
return bResult == TRUE;
|
|
}
|
|
bool Wait()
|
|
{
|
|
DWORD dwRet = ::WaitForSingleObject(this->pInfo.hProcess, INFINITE);
|
|
switch (dwRet)
|
|
{
|
|
case WAIT_FAILED:
|
|
return false;
|
|
break;
|
|
case WAIT_ABANDONED:
|
|
break;
|
|
case WAIT_OBJECT_0:
|
|
break;
|
|
case WAIT_TIMEOUT:
|
|
return false;
|
|
break;
|
|
};
|
|
return true;
|
|
}
|
|
bool Wait(int milliseconds)
|
|
{
|
|
DWORD dwRet = ::WaitForSingleObject(this->pInfo.hProcess, (DWORD)milliseconds);
|
|
switch (dwRet)
|
|
{
|
|
case WAIT_FAILED:
|
|
return false;
|
|
break;
|
|
case WAIT_ABANDONED:
|
|
break;
|
|
case WAIT_OBJECT_0:
|
|
break;
|
|
case WAIT_TIMEOUT:
|
|
return false;
|
|
break;
|
|
};
|
|
return true;
|
|
|
|
}
|
|
bool Terminate(int code = 0)
|
|
{
|
|
return ::TerminateProcess(this->pInfo.hProcess, (DWORD)code) == TRUE;
|
|
}
|
|
bool Close()
|
|
{
|
|
BOOL bCloseProcess = ::CloseHandle(this->pInfo.hProcess);
|
|
BOOL bCloseThread = ::CloseHandle(this->pInfo.hThread);
|
|
return (bCloseProcess == TRUE) && (bCloseThread == TRUE);
|
|
}
|
|
bool Stop(bool bWait, int nExitCodeSucess)
|
|
{
|
|
bool bResult = false;
|
|
if (bWait == true)
|
|
{
|
|
if (this->Wait() == false)
|
|
{
|
|
this->Terminate();
|
|
DWORD dwExitCode;
|
|
::GetExitCodeProcess(this->pInfo.hProcess, &dwExitCode);
|
|
bResult = false;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwExitCode;
|
|
::GetExitCodeProcess(this->pInfo.hProcess, &dwExitCode);
|
|
bResult = (DWORD)nExitCodeSucess == dwExitCode;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->Terminate();
|
|
this->Wait(5000);
|
|
DWORD dwExitCode;
|
|
::GetExitCodeProcess(this->pInfo.hProcess, &dwExitCode);
|
|
bResult = false;
|
|
}
|
|
this->Close();
|
|
return bResult;
|
|
}
|
|
};
|
|
}
|