|
@@ -11,18 +11,12 @@
|
|
|
#include <Userenv.h>
|
|
|
#pragma comment(lib,"userenv.lib")
|
|
|
|
|
|
-/*
|
|
|
-typedef struct _TOKEN_LINKED_TOKEN {
|
|
|
-HANDLE LinkedToken;
|
|
|
-} TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
|
|
|
-SERVICE_STATUS_HANDLE hServiceStatus;
|
|
|
-*/
|
|
|
|
|
|
CPythonExecutor::CPythonExecutor(void)
|
|
|
{
|
|
|
m_hWorkThread = NULL;
|
|
|
m_hStdoutLogThread = NULL;
|
|
|
- m_bStatus = FALSE;
|
|
|
+ m_hStderrLogThread = NULL;
|
|
|
|
|
|
m_hStdOutRead = NULL;
|
|
|
m_hStdOutWrite = NULL;
|
|
@@ -37,10 +31,7 @@ CPythonExecutor::CPythonExecutor(void)
|
|
|
memset(&m_pi, 0, sizeof(m_pi));
|
|
|
m_si.cb = sizeof(m_si);
|
|
|
|
|
|
- m_bKillProcess = FALSE;
|
|
|
m_bStopLogExport = FALSE;
|
|
|
- m_dwThreadId = 0;
|
|
|
- m_dwSubprocessId = 0;
|
|
|
|
|
|
m_pCaseObj = NULL;
|
|
|
m_ulStartTickCount = 0;
|
|
@@ -78,11 +69,6 @@ DWORD CPythonExecutor::_WorkerThread(LPVOID lpParam)
|
|
|
DWORD CPythonExecutor::_StdoutLogExportThread(LPVOID lpParam)
|
|
|
{
|
|
|
CPythonExecutor* that = (CPythonExecutor*)lpParam;
|
|
|
- if (!that) {
|
|
|
- printf("Error:参数失效\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
|
|
|
DWORD dwRead;
|
|
|
CHAR chBuf[BUFSIZE] = {0};
|
|
@@ -102,11 +88,7 @@ DWORD CPythonExecutor::_StdoutLogExportThread(LPVOID lpParam)
|
|
|
memset(chBuf, 0, BUFSIZE);
|
|
|
} while (!that->m_bStopLogExport);
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- // 结束重定向;
|
|
|
- that->EndSubprocessStdOut();
|
|
|
- GLOBAL::WriteTextLog(_T("脚本日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
|
|
|
+ GLOBAL::WriteTextLog(_T("脚本标准输出日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -114,11 +96,6 @@ DWORD CPythonExecutor::_StdoutLogExportThread(LPVOID lpParam)
|
|
|
DWORD CPythonExecutor::_StderrLogExportThread(LPVOID lpParam)
|
|
|
{
|
|
|
CPythonExecutor* that = (CPythonExecutor*)lpParam;
|
|
|
- if (!that) {
|
|
|
- printf("Error:参数失效\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
|
|
|
DWORD dwRead;
|
|
|
CHAR chBuf[BUFSIZE] = {0};
|
|
@@ -126,21 +103,18 @@ DWORD CPythonExecutor::_StderrLogExportThread(LPVOID lpParam)
|
|
|
|
|
|
do
|
|
|
{
|
|
|
- bSuccess = ReadFile(that->m_hStdOutRead, chBuf, BUFSIZE, &dwRead, NULL);
|
|
|
+ bSuccess = ReadFile(that->m_hStdErrorRead, chBuf, BUFSIZE, &dwRead, NULL);
|
|
|
if (!bSuccess || dwRead == 0 || !_tcslen(chBuf))
|
|
|
continue;
|
|
|
|
|
|
- that->m_ulStartTickCount = GetTickCount64();
|
|
|
GLOBAL::WritePythonLog(that->m_szLogPath, chBuf);
|
|
|
- // 更新日志时间;
|
|
|
- if ( that->m_pCaseObj )
|
|
|
- that->m_pCaseObj->_ulStartTickCount = GetTickCount64();
|
|
|
+ that->m_pCaseObj->_nExecutionState = 4;
|
|
|
memset(chBuf, 0, BUFSIZE);
|
|
|
- } while (!that->m_bStopLogExport);
|
|
|
-
|
|
|
+ } while (!that->m_bStopLogExport);
|
|
|
+
|
|
|
// 结束重定向;
|
|
|
that->EndSubprocessStdOut();
|
|
|
- GLOBAL::WriteTextLog(_T("脚本日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
|
|
|
+ GLOBAL::WriteTextLog(_T("脚本标准错误日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -184,8 +158,7 @@ int CPythonExecutor::RedirectSubprocessStdout(LPSTARTUPINFO si /*=NULL*/)
|
|
|
|
|
|
int CPythonExecutor::RunScriptProcess()
|
|
|
{
|
|
|
- if (!PathFileExists(m_szScriptPath))
|
|
|
- {
|
|
|
+ if (!PathFileExists(m_szScriptPath)) {
|
|
|
printf("Error:脚本路径无效\n");
|
|
|
return -1;
|
|
|
}
|
|
@@ -207,6 +180,7 @@ int CPythonExecutor::RunScriptProcess()
|
|
|
RedirectSubprocessStdout(&m_si);
|
|
|
// 恢复日志线程;
|
|
|
ResumeThread(m_hStdoutLogThread);
|
|
|
+ ResumeThread(m_hStderrLogThread);
|
|
|
|
|
|
// 启动子进程;
|
|
|
if (!CreateProcess(
|
|
@@ -226,7 +200,6 @@ int CPythonExecutor::RunScriptProcess()
|
|
|
return -3;
|
|
|
}
|
|
|
|
|
|
- m_dwSubprocessId = m_pi.dwProcessId;
|
|
|
// 等待进程完成退出.
|
|
|
WaitForSingleObject(m_pi.hProcess, INFINITE);
|
|
|
|
|
@@ -345,6 +318,7 @@ int CPythonExecutor::ServiceRunScriptProcess()
|
|
|
RedirectSubprocessStdout(&m_si);
|
|
|
// 恢复日志线程;
|
|
|
ResumeThread(m_hStdoutLogThread);
|
|
|
+ ResumeThread(m_hStderrLogThread);
|
|
|
|
|
|
// 强制stdion, stdout和stderr完全无缓冲:python -u
|
|
|
TCHAR szCommandLine[MAX_PATH] = { 0 };
|
|
@@ -369,8 +343,6 @@ int CPythonExecutor::ServiceRunScriptProcess()
|
|
|
if ( !bResult )
|
|
|
return -1;
|
|
|
|
|
|
- m_dwSubprocessId = m_pi.dwProcessId;
|
|
|
-
|
|
|
// 等待进程完成退出.
|
|
|
WaitForSingleObject(m_pi.hProcess, INFINITE);
|
|
|
|
|
@@ -406,20 +378,27 @@ int CPythonExecutor::ServiceRunScriptProcess()
|
|
|
|
|
|
bool CPythonExecutor::StartThread()
|
|
|
{
|
|
|
- // 创建线程;
|
|
|
- m_hWorkThread = CreateThread(NULL, 0, _WorkerThread, this, 0, &m_dwThreadId);
|
|
|
+ // 脚本进程运行线程;
|
|
|
+ m_hWorkThread = CreateThread(NULL, 0, _WorkerThread, this, 0, NULL);
|
|
|
if (!m_hWorkThread) {
|
|
|
printf("Error:创建执行线程失败\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- // 创建线程;
|
|
|
+ // 标准输出重定向线程;
|
|
|
m_hStdoutLogThread = CreateThread(NULL, 0, _StdoutLogExportThread, this, CREATE_SUSPENDED, NULL);
|
|
|
if (!m_hStdoutLogThread) {
|
|
|
printf("Error:创建日志线程失败\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ // 标准错误重定向线程;
|
|
|
+ m_hStderrLogThread = CreateThread(NULL, 0, _StderrLogExportThread, this, CREATE_SUSPENDED, NULL);
|
|
|
+ if (!m_hStderrLogThread) {
|
|
|
+ printf("Error:创建日志线程失败\n");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -451,13 +430,13 @@ void CPythonExecutor::EndWorkThread()
|
|
|
|
|
|
void CPythonExecutor::EndLogThread()
|
|
|
{
|
|
|
+ // 标记结束;
|
|
|
m_bStopLogExport = TRUE;
|
|
|
// 等待3秒,是否能自主结束线程;
|
|
|
if ( m_hStdoutLogThread ) {
|
|
|
if ( WaitForSingleObject(m_hStdoutLogThread, 3000) == WAIT_OBJECT_0 ) {
|
|
|
CloseHandle(m_hStdoutLogThread);
|
|
|
m_hStdoutLogThread = NULL;
|
|
|
- return;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -472,6 +451,26 @@ void CPythonExecutor::EndLogThread()
|
|
|
CloseHandle(m_hStdoutLogThread);
|
|
|
m_hStdoutLogThread = NULL;
|
|
|
}
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ if ( m_hStderrLogThread ) {
|
|
|
+ if ( WaitForSingleObject(m_hStderrLogThread, 3000) == WAIT_OBJECT_0 ) {
|
|
|
+ CloseHandle(m_hStderrLogThread);
|
|
|
+ m_hStderrLogThread = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 手动结束线程;
|
|
|
+ if (m_hStderrLogThread) {
|
|
|
+ // 尝试5次结束行为;
|
|
|
+ for (int i = 0; i < 5; i++) {
|
|
|
+ if (TerminateThread(m_hStderrLogThread, 0))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseHandle(m_hStderrLogThread);
|
|
|
+ m_hStderrLogThread = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CPythonExecutor::EndThread()
|
|
@@ -496,8 +495,12 @@ BOOL CPythonExecutor::EndSubprocess()
|
|
|
|
|
|
void CPythonExecutor::EndSubprocessStdOut()
|
|
|
{
|
|
|
- OutputDebugString("--------------EndSubprocessStdOut----------------\n");
|
|
|
+ OutputDebugString("关闭重定向子进程标准输出管道句柄\n");
|
|
|
// 关闭重定向句柄;
|
|
|
+ if (m_hStdErrorRead)
|
|
|
+ CloseHandle(m_hStdErrorRead);
|
|
|
+ m_hStdErrorRead = NULL;
|
|
|
+
|
|
|
if (m_hStdErrorWrite)
|
|
|
CloseHandle(m_hStdErrorWrite);
|
|
|
m_hStdErrorWrite = NULL;
|
|
@@ -533,139 +536,6 @@ DWORD CPythonExecutor::GetActiveSessionID()
|
|
|
return dwSessionId;
|
|
|
}
|
|
|
|
|
|
-BOOL CPythonExecutor::ServiceExecute(std::wstring wstrCmdLine, INT32& n32ExitResult)
|
|
|
-{
|
|
|
- ofstream ofile("C:\\logEvent.txt");
|
|
|
- ofile<<"start excute"<<std::endl;
|
|
|
- DWORD dwProcesses = 0;
|
|
|
- BOOL bResult = FALSE;
|
|
|
-
|
|
|
- DWORD dwSid = GetActiveSessionID();
|
|
|
-
|
|
|
- DWORD dwRet = 0;
|
|
|
- PROCESS_INFORMATION pi;
|
|
|
- STARTUPINFO si;
|
|
|
- HANDLE hProcess = NULL, hPToken = NULL, hUserTokenDup = NULL;
|
|
|
- if (!WTSQueryUserToken(dwSid, &hPToken)) {
|
|
|
- PROCESSENTRY32 procEntry;
|
|
|
- DWORD dwPid = 0;
|
|
|
- HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
- if (hSnap == INVALID_HANDLE_VALUE) {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- procEntry.dwSize = sizeof(PROCESSENTRY32);
|
|
|
- if (Process32First(hSnap, &procEntry)) {
|
|
|
- do {
|
|
|
- if (_tcsicmp(procEntry.szExeFile, _T("explorer.exe")) == 0) {
|
|
|
- DWORD exeSessionId = 0;
|
|
|
- if (ProcessIdToSessionId(procEntry.th32ProcessID, &exeSessionId) && exeSessionId == dwSid) {
|
|
|
- dwPid = procEntry.th32ProcessID;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- } while (Process32Next(hSnap, &procEntry));
|
|
|
- }
|
|
|
- CloseHandle(hSnap);
|
|
|
-
|
|
|
- // explorer进程不存在
|
|
|
- if (dwPid == 0)
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
|
|
|
- if (hProcess == NULL) {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- if(!::OpenProcessToken(hProcess, TOKEN_ALL_ACCESS_P,&hPToken)) {
|
|
|
- CloseHandle(hProcess);
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hPToken == NULL)
|
|
|
- return FALSE;
|
|
|
-
|
|
|
- TOKEN_LINKED_TOKEN admin;
|
|
|
- bResult = GetTokenInformation(hPToken, (TOKEN_INFORMATION_CLASS)19, &admin, sizeof(TOKEN_LINKED_TOKEN), &dwRet);
|
|
|
-
|
|
|
- if (!bResult) {// vista 以前版本不支持TokenLinkedToken
|
|
|
- TOKEN_PRIVILEGES tp;
|
|
|
- LUID luid;
|
|
|
- if (LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid)) {
|
|
|
- tp.PrivilegeCount =1;
|
|
|
- tp.Privileges[0].Luid =luid;
|
|
|
- tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
|
|
|
- }
|
|
|
- DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
|
|
|
- } else {
|
|
|
- hUserTokenDup = admin.LinkedToken;
|
|
|
- ofile<<"token: "<<hUserTokenDup<<std::endl;
|
|
|
- }
|
|
|
-
|
|
|
- LPVOID pEnv =NULL;
|
|
|
- DWORD dwCreationFlags = CREATE_PRESERVE_CODE_AUTHZ_LEVEL;
|
|
|
-
|
|
|
- if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE)) {
|
|
|
- dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
|
|
|
- } else {
|
|
|
- pEnv = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- ZeroMemory( &si, sizeof(si) );
|
|
|
- si.cb = sizeof(si);
|
|
|
- si.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
- si.wShowWindow = SW_SHOWNORMAL;
|
|
|
- ZeroMemory( &pi, sizeof(pi) );
|
|
|
-
|
|
|
- bResult = CreateProcessAsUser(
|
|
|
- hUserTokenDup, // client's access token
|
|
|
- NULL, // file to execute
|
|
|
- (LPTSTR) wstrCmdLine.c_str(), // command line
|
|
|
- NULL, // pointer to process SECURITY_ATTRIBUTES
|
|
|
- NULL, // pointer to thread SECURITY_ATTRIBUTES
|
|
|
- FALSE, // handles are not inheritable
|
|
|
- dwCreationFlags, // creation flags
|
|
|
- pEnv, // pointer to new environment block
|
|
|
- NULL, // name of current directory
|
|
|
- &si, // pointer to STARTUPINFO structure
|
|
|
- &pi // receives information about new process
|
|
|
- );
|
|
|
-
|
|
|
- if(pi.hProcess) {
|
|
|
- if(WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, 180000)) {
|
|
|
- DWORD dwResult = 0;
|
|
|
- if(GetExitCodeProcess(pi.hProcess, &dwResult)) {
|
|
|
- n32ExitResult = dwResult;
|
|
|
- } else {
|
|
|
- n32ExitResult = -1;
|
|
|
- }
|
|
|
-
|
|
|
- CloseHandle(pi.hThread);
|
|
|
- CloseHandle(pi.hProcess);
|
|
|
- } else {
|
|
|
- CloseHandle(pi.hThread);
|
|
|
- CloseHandle(pi.hProcess);
|
|
|
- n32ExitResult = -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hUserTokenDup != NULL)
|
|
|
- CloseHandle(hUserTokenDup);
|
|
|
- if (hProcess != NULL)
|
|
|
- CloseHandle(hProcess);
|
|
|
- if (hPToken != NULL)
|
|
|
- CloseHandle(hPToken);
|
|
|
- if (pEnv != NULL)
|
|
|
- DestroyEnvironmentBlock(pEnv);
|
|
|
-
|
|
|
- return TRUE;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
bool CPythonExecutor::InitScript(std::string strScript, std::string strLogPath, std::string strScriptCmd)
|
|
|
{
|
|
|
// 判断脚本是否存在;
|
|
@@ -692,7 +562,6 @@ bool CPythonExecutor::InitScript(std::string strScript, std::string strLogPath,
|
|
|
}
|
|
|
|
|
|
// 赋值参数;
|
|
|
- m_dwThreadId = m_dwSubprocessId = 0;
|
|
|
_tcscpy_s(m_szScriptPath, strScript.c_str());
|
|
|
_tcscpy_s(m_szLogPath, strLogPath.c_str());
|
|
|
_tcscpy_s(m_szExtraSentence, strScriptCmd.c_str());
|
|
@@ -707,9 +576,6 @@ bool CPythonExecutor::StartScript()
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- // 异常类型;
|
|
|
- printf("Error:异常类型脚本\n");
|
|
|
-
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -723,7 +589,9 @@ void CPythonExecutor::StopScript()
|
|
|
|
|
|
bool CPythonExecutor::IsScriptOver()
|
|
|
{
|
|
|
- if ( WaitForSingleObject(m_hStdoutLogThread, 0) == WAIT_OBJECT_0 && WaitForSingleObject(m_hWorkThread, 0) == WAIT_OBJECT_0)
|
|
|
+ if ( WaitForSingleObject(m_hStdoutLogThread, 0) == WAIT_OBJECT_0 &&
|
|
|
+ WaitForSingleObject(m_hStderrLogThread, 0) == WAIT_OBJECT_0 &&
|
|
|
+ WaitForSingleObject(m_hWorkThread, 0) == WAIT_OBJECT_0)
|
|
|
{
|
|
|
GLOBAL::WriteTextLog(_T("====>脚本(%s)已完成"), m_pCaseObj->strCaseName.c_str());
|
|
|
return true;
|