1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060 |
- #include "StdAfx.h"
- #include "ScriptExecutor.h"
- #include <fstream>
- #include <io.h>
- #include <fcntl.h>
- #include "Python.h"
- // 服务进程头文件;
- #include <Wtsapi32.h>
- #include <TlHelp32.h>
- #pragma comment(lib, "wtsapi32.lib")
- #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;
- */
- CScriptExecutor::CScriptExecutor(void)
- {
- m_hWorkThread = NULL;
- m_hStdoutLogThread = NULL;
- m_bStatus = FALSE;
- m_nRunType = 0;
- m_hStdOutRead = NULL;
- m_hStdOutWrite = NULL;
- m_hStdErrorRead = NULL;
- m_hStdErrorWrite = NULL;
- m_hOldStdOutWrite = NULL;
- memset(m_szScriptPath, 0, MAX_PATH);
- memset(m_szLogPath, 0, MAX_PATH);
- memset(m_szExtraSentence, 0, MAX_PATH);
- memset(&m_si, 0, sizeof(m_si));
- 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_bRuned = FALSE;
- m_pCaseObj = NULL;
- m_ulStartTickCount = 0;
- }
- CScriptExecutor::~CScriptExecutor(void)
- {
- EndWorkThread();
- EndLogThread();
- }
- DWORD CScriptExecutor::_WorkerThread(LPVOID lpParam)
- {
- CScriptExecutor* that = (CScriptExecutor*)lpParam;
- if ( !that ) {
- printf("Error:参数失效\n");
- return -1;
- }
- if ( that->m_nRunType == EMBEDDED ) {
- that->RedirectProcessStdout();
- ResumeThread(that->m_hStdoutLogThread);
- that->RunEmbeddedScript();
- }
- else if (that->m_nRunType == SUBPROCESS) {
- #ifdef _DEBUG
- that->RunScriptProcess();
- #else
- that->ServiceRunScriptProcess();
- #endif
- }
- // 延时;
- Sleep(2000);
- // 结束日志线程;
- that->m_bStopLogExport = TRUE;
- GLOBAL::WriteTextLog(_T("脚本执行线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
- return 0;
- }
- DWORD CScriptExecutor::_StdoutLogExportThread(LPVOID lpParam)
- {
- CScriptExecutor* that = (CScriptExecutor*)lpParam;
- if (!that) {
- printf("Error:参数失效\n");
- return -1;
- }
- if (that->m_nRunType == SUBPROCESS)
- {
- DWORD dwRead;
- CHAR chBuf[BUFSIZE] = {0};
- BOOL bSuccess = FALSE;
-
- do
- {
- bSuccess = ReadFile(that->m_hStdOutRead, 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();
- memset(chBuf, 0, BUFSIZE);
- } while (!that->m_bStopLogExport);
- }
- else if ( that->m_nRunType == EMBEDDED)
- {
- DWORD dwRead;
- CHAR chBuf[BUFSIZE] = {0};
- BOOL bSuccess = FALSE;
- do
- {
- bSuccess = ReadFile(that->m_hStdOutRead, 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();
- memset(chBuf, 0, BUFSIZE);
- } while (!that->m_bStopLogExport);
- }
- // 结束重定向;
- that->EndSubprocessStdOut();
- GLOBAL::WriteTextLog(_T("脚本日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
- return 0;
- }
- DWORD CScriptExecutor::_StderrLogExportThread(LPVOID lpParam)
- {
- CScriptExecutor* that = (CScriptExecutor*)lpParam;
- if (!that) {
- printf("Error:参数失效\n");
- return -1;
- }
- if (that->m_nRunType == SUBPROCESS)
- {
- DWORD dwRead;
- CHAR chBuf[BUFSIZE] = {0};
- BOOL bSuccess = FALSE;
- do
- {
- bSuccess = ReadFile(that->m_hStdOutRead, 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();
- memset(chBuf, 0, BUFSIZE);
- } while (!that->m_bStopLogExport);
- }
- else if ( that->m_nRunType == EMBEDDED)
- {
- DWORD dwRead;
- CHAR chBuf[BUFSIZE] = {0};
- BOOL bSuccess = FALSE;
- do
- {
- bSuccess = ReadFile(that->m_hStdOutRead, 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();
- memset(chBuf, 0, BUFSIZE);
- } while (!that->m_bStopLogExport);
- }
- // 结束重定向;
- that->EndSubprocessStdOut();
- GLOBAL::WriteTextLog(_T("脚本日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
- return 0;
- }
- int CScriptExecutor::RedirectSubprocessStdout(LPSTARTUPINFO si /*=NULL*/)
- {
- #ifdef _DEBUG
- OutputDebugString("RedirectSubprocessStdout\n");
- #endif
- // Python脚本中,必须使用sys.__stdout__()
- if (m_nRunType == SUBPROCESS) {
- SECURITY_ATTRIBUTES sa;
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof(sa);
- // 创建stdout的管道;
- if (!CreatePipe(&m_hStdOutRead, &m_hStdOutWrite, &sa, 0)) {
- OutputDebugString("Error:创建stdout管道失败\n");
- return -1;
- }
- #if 0// 标准输出和标准错误都由同一个句柄重定向,此时只需要一个线程来读取管道内容;
- // 创建stderr的管道,由于stderr一般就是stdout,直接复制句柄;
- if (!DuplicateHandle(GetCurrentProcess(), m_hStdOutWrite, GetCurrentProcess(), &m_hStdErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
- OutputDebugString("创建stderr管道失败\n");
- return -2;
- }
- #else
- // 标准输出和标准错误分开,需要二个线程来读取管道内容;
- if (!CreatePipe(&m_hStdErrorRead, &m_hStdErrorWrite, &sa, 0)) {
- OutputDebugString("Error:创建stderr管道失败\n");
- return -1;
- }
- #endif
- si->dwFlags |= STARTF_USESTDHANDLES;
- // 将子进程的stdout输出到句柄hStdOutWrite;
- si->hStdOutput = m_hStdOutWrite;
- // 将子进程的stderr输出到句柄hStdErrWrite;
- si->hStdError = m_hStdErrorWrite;
- return 0;
- }
- // 异常类型;
- OutputDebugString("Error:异常类型\n");
- return -5;
- }
- int CScriptExecutor::RedirectProcessStdout()
- {
- #ifdef _DEBUG
- OutputDebugString("RedirectProcessStdout\n");
- #endif
- if (m_nRunType == EMBEDDED) {
- // 创建stdout的管道;
- if (!CreatePipe(&m_hStdOutRead, &m_hStdOutWrite, NULL, 0)) {
- printf("Error:创建stdout管道失败\n");
- return -1;
- }
- // 将 C 运行时文件描述符与现有操作系统文件句柄关联;
- int wpfd = _open_osfhandle((intptr_t)m_hStdOutWrite, _O_TEXT);
- // 为stdout分配新文件描述符;
- if (_dup2(wpfd, _fileno(stdout)) != 0) {
- printf("Error:dup2调用失败");
- return -2;
- }
- _close(wpfd);
- // 备份进程原始标准输出;
- m_hOldStdOutWrite = GetStdHandle(STD_OUTPUT_HANDLE);
- // 设备进程标准输出,重定向到管道中;
- if (!SetStdHandle(STD_OUTPUT_HANDLE, m_hStdOutWrite)) {
- printf("Error:重定向失败\n");
- return -3;
- }
- // 设置标准流不使用缓冲,即时写入;
- setvbuf(stdout, NULL, _IONBF, 0);
- return 0;
- }
- // 异常类型;
- printf("Error:异常类型\n");
- return -5;
- }
- void CScriptExecutor::CatchPythonException()
- {
- if (!Py_IsInitialized())
- {
- printf("Error:未初始化Python环境\n");
- return;
- }
- if (!PyErr_Occurred())
- {
- printf("Error:没有异常产生\n");
- return;
- }
- // 捕获异常;
- const char* pszErrMsg = NULL;
- TCHAR* pszTraceback = NULL;
- PyObject* pPyType = NULL;
- PyObject* pPyValue = NULL;
- PyObject* pPyTraceback = NULL;
- // 非控制台,使用PyErr_Fetch捕获异常;
- PyErr_Fetch(&pPyType, &pPyValue, &pPyTraceback);
- PyErr_NormalizeException(&pPyType, &pPyValue, &pPyTraceback); // 可有可无,不影响获取异常;
- if (pPyValue) {
- PyObject* pPyStr = PyObject_Str(pPyValue);
- if (PyString_Check(pPyStr)) {
- pszErrMsg = PyString_AsString(pPyStr);
- if (pszErrMsg)
- printf("Error Info=>%s\n", pszErrMsg);
- if (pPyTraceback) {
- PyObject* pPyTraceModule = PyImport_ImportModule("traceback");
- if (!pPyTraceModule)
- {
- printf("Error:导入traceback模块失败\n");
- return;
- }
- #if 1 // 细分出所有换行符;
- PyObject* pPyModuleDict = PyModule_GetDict(pPyTraceModule);
- if (pPyModuleDict) {
- PyObject* pPyFunc = PyDict_GetItemString(pPyModuleDict, "format_exception");
- if (!pPyFunc || !PyCallable_Check(pPyFunc)) {
- printf("Error:加载format_exception失败\n");
- return;
- }
- PyObject* pErroList = PyObject_CallFunctionObjArgs(pPyFunc, pPyType, pPyValue, pPyTraceback, NULL);
- if (pErroList) {
- int nSize = PyList_Size(pErroList);
- for (int i = 0; i < nSize; i++) {
- pszErrMsg = PyString_AsString(PyList_GetItem(pErroList, i));
- printf("%s", pszErrMsg);
- }
- }
- Py_DECREF(pErroList);
- }
- Py_XDECREF(pPyTraceModule);
- #else // 不细分Item;
- PyObject* pPyFunc = PyObject_GetAttrString(pPyTraceModule, "format_exception");
- if (!pPyFunc || !PyCallable_Check(pPyFunc))
- {
- printf("Error:加载format_exception失败\n");
- return;
- }
- PyObject* pPyResult = PyObject_CallFunctionObjArgs(pPyFunc, pPyType, pPyValue, pPyTraceback, NULL);
- pPyStr = PyObject_Str(pPyResult);
- pszErrMsg = PyString_AsString(pPyStr);
- if (pszErrMsg)
- printf("%s\n", pszErrMsg);
- Py_DECREF(pPyResult);
- Py_XDECREF(pPyTraceModule);
- #endif
- }
- }
- }
- Py_XDECREF(pPyType);
- Py_XDECREF(pPyValue);
- Py_XDECREF(pPyTraceback);
- }
- int CScriptExecutor::RunEmbeddedScript()
- {
- // 参数有效性判断;
- if (!PathFileExists(m_szScriptPath)) {
- printf("Error:脚本文件不存在\n");
- return -1;
- }
- // 初始化Python环境;
- if (!Py_IsInitialized())
- Py_Initialize();
- if (!Py_IsInitialized()) {
- printf("Error:初始化Python环境失败\n");
- return -2;
- }
- // 解析脚本路径和脚本名称;
- std::string scriptdir;
- TCHAR szDrive[_MAX_DRIVE] = { 0 };
- TCHAR szDir[_MAX_DIR] = { 0 };
- TCHAR szExt[_MAX_EXT] = { 0 };
- TCHAR szFilename[_MAX_FNAME] = { 0 };
- TCHAR szScriptDir[MAX_PATH] = { 0 };
- _tsplitpath_s(m_szScriptPath, szDrive, szDir, szFilename, szExt);
- _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
- // 缓存一份路径;
- scriptdir = szScriptDir;
- // 将'\'转换成'/', Python才设置运行目录成功;
- int len = _tcslen(szScriptDir);
- for (int i = 0; i < len; i++) {
- if (szScriptDir[i] == '\\')
- szScriptDir[i] = '/';
- }
- //szScriptDir[len-1] = '\0';
- TCHAR szExecuteDir[MAX_PATH] = { 0 };
- _stprintf_s(szExecuteDir, _T("sys.path.append(\"%s\")"), szScriptDir);
- // 添加系统模块,并指定当前脚本路径为运行路径;
- PyRun_SimpleString("import sys");
- PyRun_SimpleString(szExecuteDir);
- // 运行额外的语句,一般用于传递命令行参数;
- if (_tcslen(m_szExtraSentence))
- PyRun_SimpleString(m_szExtraSentence);
- // 注意:脚本名称尽量不要与系统目录其他py文件相同;
- // 导入脚本,以脚本名称为模块名加载;
- PyObject* pModuleObj = PyImport_ImportModule(szFilename);
- if (!pModuleObj)
- {
- printf("Error:加载脚本模块失败\n");
- Py_Finalize();
- return -3;
- }
- // 获取脚本的主函数名称(规定所有脚本的主函数名为main)
- // 加载函数:注意,如果目录下有同名的脚本文件,可能会加载失败;
- PyObject* pFunction = PyObject_GetAttrString(pModuleObj, "main");
- if (!pFunction || !PyCallable_Check(pFunction))
- {
- printf("Error:加载函数失败\n");
- Py_Finalize();
- return -4;
- }
- // 执行main函数;
- PyObject* pResult = PyObject_CallObject(pFunction, NULL);
- if (!pResult)
- {
- printf("Error:执行函数失败\n");
- CatchPythonException();
- Py_Finalize();
-
- return -5;
- }
- // 延时;
- Sleep(2000);
- // 结束日志线程;
- m_bStopLogExport = TRUE;
- // 同时需要关闭输出的管道,否则ReadFile会阻塞;
- CloseHandle(m_hStdOutWrite);
- m_hStdOutWrite = NULL;
- CloseHandle(m_hStdErrorWrite);
- m_hStdErrorWrite = NULL;
- Py_DECREF(pResult);
- Py_Finalize();
- return 0;
- }
- int CScriptExecutor::RunScriptProcess()
- {
- if (!PathFileExists(m_szScriptPath))
- {
- printf("Error:脚本路径无效\n");
- return -1;
- }
- // 初始化参数;
- ::memset(&m_si, 0, sizeof(m_si));
- ::memset(&m_pi, 0, sizeof(m_pi));
- m_si.cb = sizeof(m_si);
- GetStartupInfo(&m_si);
- // 强制stdion, stdout和stderr完全无缓冲:python -u
- TCHAR szCommandLine[MAX_PATH] = { 0 };
- if (_tcslen(m_szExtraSentence))
- _stprintf_s(szCommandLine, _T("python -W ignore -u %s %s"), m_szScriptPath, m_szExtraSentence);
- else
- _stprintf_s(szCommandLine, _T("python -W ignore -u %s"), m_szScriptPath);
- // 重定向输出;
- RedirectSubprocessStdout(&m_si);
- // 恢复日志线程;
- ResumeThread(m_hStdoutLogThread);
- // 启动子进程;
- if (!CreateProcess(
- NULL, // No module name (use command line)
- szCommandLine, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- TRUE, // Set handle inheritance to TRUE
- 0, // No creation flags
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
- &m_si, // Pointer to STARTUPINFO structure
- &m_pi) // Pointer to PROCESS_INFORMATION structure
- )
- {
- GLOBAL::WriteTextLog("Error:创建子进程失败 (%d)", GetLastError());
- return -3;
- }
- m_bRuned = TRUE;
- m_dwSubprocessId = m_pi.dwProcessId;
- // 等待进程完成退出.
- WaitForSingleObject(m_pi.hProcess, INFINITE);
- Sleep(5000);
- GLOBAL::WriteTextLog("脚本进程结束(%ld)", m_pi.dwProcessId);
- // 结束日志线程;
- m_bStopLogExport = TRUE;
- // 同时需要关闭输出的管道,否则ReadFile会阻塞;
- CloseHandle(m_hStdOutWrite);
- m_hStdOutWrite = NULL;
- CloseHandle(m_hStdErrorWrite);
- m_hStdErrorWrite = NULL;
- // 关闭进程句柄.
- CloseHandle(m_pi.hProcess);
- CloseHandle(m_pi.hThread);
- // 重置;
- memset(&m_si, 0, sizeof(m_si));
- memset(&m_pi, 0, sizeof(m_pi));
- m_si.cb = sizeof(m_si);
- return 0;
- }
- int CScriptExecutor::ServiceRunScriptProcess()
- {
- if (!PathFileExists(m_szScriptPath)) {
- printf("Error:脚本路径无效\n");
- return -1;
- }
- DWORD dwProcesses = 0;
- BOOL bResult = FALSE;
- DWORD dwRet = 0;
- DWORD dwSid = GetActiveSessionID();
-
- 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 -1;
- 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;
- }
- LPVOID pEnv =NULL;
- DWORD dwCreationFlags = CREATE_PRESERVE_CODE_AUTHZ_LEVEL;
- if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
- {
- dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
- }
- else
- {
- pEnv = NULL;
- }
- ZeroMemory( &m_si, sizeof(m_si) );
- m_si.cb = sizeof(m_si);
- m_si.dwFlags = STARTF_USESHOWWINDOW;
- m_si.wShowWindow = SW_HIDE;
- ZeroMemory( &m_pi, sizeof(m_pi) );
- // 重定向输出;
- RedirectSubprocessStdout(&m_si);
- // 恢复日志线程;
- ResumeThread(m_hStdoutLogThread);
- // 强制stdion, stdout和stderr完全无缓冲:python -u
- TCHAR szCommandLine[MAX_PATH] = { 0 };
- if (_tcslen(m_szExtraSentence))
- _stprintf_s(szCommandLine, _T("python -W ignore -u %s %s"), m_szScriptPath, m_szExtraSentence);
- else
- _stprintf_s(szCommandLine, _T("python -W ignore -u %s"), m_szScriptPath);
- bResult = CreateProcessAsUser(
- hUserTokenDup, // client's access token
- NULL, // file to execute
- szCommandLine, // command line
- NULL, // pointer to process SECURITY_ATTRIBUTES
- NULL, // pointer to thread SECURITY_ATTRIBUTES
- TRUE, // handles are not inheritable
- dwCreationFlags, // creation flags
- pEnv, // pointer to new environment block
- NULL, // name of current directory
- &m_si, // pointer to STARTUPINFO structure
- &m_pi // receives information about new process
- );
- if ( !bResult )
- return -1;
- m_bRuned = TRUE;
- m_dwSubprocessId = m_pi.dwProcessId;
- // 等待进程完成退出.
- WaitForSingleObject(m_pi.hProcess, INFINITE);
- Sleep(5000);
- // 结束日志线程;
- m_bStopLogExport = TRUE;
- // 关闭进程句柄.
- CloseHandle(m_pi.hProcess);
- CloseHandle(m_pi.hThread);
- // 同时需要关闭输出的管道,否则ReadFile会阻塞;
- CloseHandle(m_hStdOutWrite);
- m_hStdOutWrite = NULL;
- CloseHandle(m_hStdErrorWrite);
- m_hStdErrorWrite = NULL;
- // 重置;
- memset(&m_si, 0, sizeof(m_si));
- memset(&m_pi, 0, sizeof(m_pi));
- m_si.cb = sizeof(m_si);
- if (hUserTokenDup != NULL)
- CloseHandle(hUserTokenDup);
- if (hProcess != NULL)
- CloseHandle(hProcess);
- if (hPToken != NULL)
- CloseHandle(hPToken);
- if (pEnv != NULL)
- DestroyEnvironmentBlock(pEnv);
- return TRUE;
- }
- bool CScriptExecutor::StartThread()
- {
- // 创建线程;
- m_hWorkThread = CreateThread(NULL, 0, _WorkerThread, this, 0, &m_dwThreadId);
- 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;
- }
- return true;
- }
- void CScriptExecutor::EndWorkThread()
- {
- // 结束进程;
- EndSubprocess();
- // 等待3秒,是否能自主结束线程;
- if (m_hWorkThread) {
- if (WaitForSingleObject(m_hWorkThread, 3000) == WAIT_OBJECT_0) {
- CloseHandle(m_hWorkThread);
- m_hWorkThread = NULL;
- return;
- }
- }
- // 手动结束线程;
- if ( m_hWorkThread ) {
- // 尝试5次结束行为;
- for (int i = 0; i < 5; i++) {
- if (TerminateThread(m_hWorkThread, 0))
- break;
- }
- CloseHandle(m_hWorkThread);
- m_hWorkThread = NULL;
- }
- }
- void CScriptExecutor::EndLogThread()
- {
- m_bStopLogExport = TRUE;
- // 等待3秒,是否能自主结束线程;
- if ( m_hStdoutLogThread ) {
- if ( WaitForSingleObject(m_hStdoutLogThread, 3000) == WAIT_OBJECT_0 ) {
- CloseHandle(m_hStdoutLogThread);
- m_hStdoutLogThread = NULL;
- return;
- }
- }
- // 手动结束线程;
- if (m_hStdoutLogThread) {
- // 尝试5次结束行为;
- for (int i = 0; i < 5; i++) {
- if (TerminateThread(m_hStdoutLogThread, 0))
- break;
- }
- CloseHandle(m_hStdoutLogThread);
- m_hStdoutLogThread = NULL;
- }
- }
- void CScriptExecutor::EndThread()
- {
- EndWorkThread();
- EndLogThread();
- }
- BOOL CScriptExecutor::EndSubprocess()
- {
- BOOL ret = false;
- if (m_pi.hProcess) {
- // 尝试5次结束;
- for (int i = 0; i < 5; i++) {
- if ( (ret = TerminateProcess(m_pi.hProcess, 0)) )
- break;
- }
- }
- return ret;
- }
- void CScriptExecutor::EndProcessStdOut()
- {
- OutputDebugString("--------------EndProcessStdOut----------------\n");
- #if 0 // 恢复失败,代码有问题
- // 恢复标准输出(嵌入进程脚本);
- if ( m_nRunType == EMBEDDED && m_hOldStdOutWrite)
- {
- int fn = _fileno(stdout);
- // 恢复进程默认标准输出;
- int fd = _open_osfhandle((intptr_t)m_hOldStdOutWrite, _O_RDWR);
- if ( _dup2(fd, _fileno(stdout)) == 0)
- {
- _close(fd);
- // 设置标准输出;
- SetStdHandle(STD_OUTPUT_HANDLE, m_hOldStdOutWrite);
- m_hOldStdOutWrite = NULL;
- // 设置标准流不使用缓冲,即时写入;
- setvbuf(stdout, NULL, _IONBF, 0);
- }
- else
- {
- printf("Error:_dup2分配文件描述符失败\n");
- }
- }
- #endif
- // 关闭重定向句柄;
- if (m_hStdErrorWrite)
- CloseHandle(m_hStdErrorWrite);
- m_hStdErrorWrite = NULL;
- // 只有子进程方式才关闭句柄;
- if ( m_hStdOutWrite)
- CloseHandle(m_hStdOutWrite);
- m_hStdOutWrite = NULL;
- if (m_hStdOutRead)
- CloseHandle(m_hStdOutRead);
- m_hStdOutRead = NULL;
- }
- void CScriptExecutor::EndSubprocessStdOut()
- {
- OutputDebugString("--------------EndSubprocessStdOut----------------\n");
- // 关闭重定向句柄;
- if (m_hStdErrorWrite)
- CloseHandle(m_hStdErrorWrite);
- m_hStdErrorWrite = NULL;
- // 只有子进程方式才关闭句柄;
- if ( m_hStdOutWrite)
- CloseHandle(m_hStdOutWrite);
- m_hStdOutWrite = NULL;
- if (m_hStdOutRead)
- CloseHandle(m_hStdOutRead);
- m_hStdOutRead = NULL;
- }
- DWORD CScriptExecutor::GetActiveSessionID()
- {
- DWORD dwSessionId = 0;
- PWTS_SESSION_INFO pSessionInfo = NULL;
- DWORD dwCount = 0;
- WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
- for(DWORD i = 0; i < dwCount; i++) {
- WTS_SESSION_INFO si = pSessionInfo[i];
- if(WTSActive == si.State) {
- dwSessionId = si.SessionId;
- break;
- }
- }
- WTSFreeMemory(pSessionInfo);
- return dwSessionId;
- }
- BOOL CScriptExecutor::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 CScriptExecutor::InitScript(std::string strScript, std::string strLogPath, std::string strScriptCmd, int nRunType /*= PY_RUN_TYPE::EMBEDDED*/)
- {
- // 判断脚本是否存在;
- if (!PathFileExists(strScript.c_str())) {
- printf("Error:脚本文件不存在\n");
- return false;
- }
- // 判断日志文件路径是否可创建;
- if (!PathFileExists(strLogPath.c_str())) {
- // 创建路径;
- if (!GLOBAL::MKDIR(strLogPath.c_str())) {
- printf("Error:创建目录失败\n");
- return false;
- }
- // 创建文件;
- std::ofstream flog(strLogPath.c_str());
- if ( flog.bad() ) {
- printf("Error:创建文件失败\n");
- return false;
- }
- flog.close();
- }
- // 赋值参数;
- m_bRuned = FALSE;
- m_nRunType = nRunType;
- 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());
- return true;
- }
- bool CScriptExecutor::StartScript()
- {
- if (StartThread()) {
- Sleep(100);
- return true;
- }
- // 异常类型;
- printf("Error:异常类型脚本\n");
- return false;
- }
- void CScriptExecutor::StopScript()
- {
- // 如果是子进程运行脚本,停止线程时kill进程;
- if (m_nRunType == SUBPROCESS)
- EndSubprocess();
- // 结束线程;
- EndWorkThread();
- }
- bool CScriptExecutor::IsScriptOver()
- {
- if ( WaitForSingleObject(m_hStdoutLogThread, 0) == WAIT_OBJECT_0 && WaitForSingleObject(m_hWorkThread, 0) == WAIT_OBJECT_0)
- {
- GLOBAL::WriteTextLog(_T("====>脚本(%s)已完成"), m_pCaseObj->strCaseName.c_str());
- return true;
- }
- return false;
- }
|