PythonExecutor.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. #include "StdAfx.h"
  2. #include "PythonExecutor.h"
  3. #include <fstream>
  4. #include <io.h>
  5. #include <fcntl.h>
  6. #include "Python.h"
  7. // 服务进程头文件;
  8. #include <Wtsapi32.h>
  9. #include <TlHelp32.h>
  10. #pragma comment(lib, "wtsapi32.lib")
  11. #include <Userenv.h>
  12. #pragma comment(lib,"userenv.lib")
  13. CPythonExecutor::CPythonExecutor(void)
  14. {
  15. m_hWorkThread = NULL;
  16. m_hStdoutLogThread = NULL;
  17. m_hStderrLogThread = NULL;
  18. m_hStdOutRead = NULL;
  19. m_hStdOutWrite = NULL;
  20. m_hStdErrorRead = NULL;
  21. m_hStdErrorWrite = NULL;
  22. memset(m_szScriptPath, 0, MAX_PATH);
  23. memset(m_szLogPath, 0, MAX_PATH);
  24. memset(m_szExtraSentence, 0, MAX_PATH);
  25. memset(&m_si, 0, sizeof(m_si));
  26. memset(&m_pi, 0, sizeof(m_pi));
  27. m_si.cb = sizeof(m_si);
  28. m_bStopLogExport = FALSE;
  29. m_pCaseObj = NULL;
  30. m_ulStartTickCount = 0;
  31. }
  32. CPythonExecutor::~CPythonExecutor(void)
  33. {
  34. TRACE1("\t~CPythonExecutor:%p\n\n", this);
  35. EndLogThread();
  36. EndWorkThread();
  37. }
  38. DWORD CPythonExecutor::_WorkerThread(LPVOID lpParam)
  39. {
  40. CPythonExecutor* that = (CPythonExecutor*)lpParam;
  41. #if (defined _DEBUG && !defined DBG_SERVER) || defined RTEST
  42. that->RunScriptProcess();
  43. #else
  44. that->ServiceRunScriptProcess();
  45. #endif
  46. // 延时;
  47. Sleep(2000);
  48. // 结束日志线程;
  49. that->m_bStopLogExport = TRUE;
  50. // 可能出错:m_pCaseObj可能会提前释放了,所以需要保证不能提前释放;
  51. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("脚本执行线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
  52. return 0;
  53. }
  54. DWORD CPythonExecutor::_StdoutLogExportThread(LPVOID lpParam)
  55. {
  56. CPythonExecutor* that = (CPythonExecutor*)lpParam;
  57. DWORD dwBytesToRead;
  58. CHAR chBuf[BUFSIZE] = {0};
  59. BOOL bSuccess = FALSE;
  60. do
  61. {
  62. // 预览管道中数据,有才ReadFile;
  63. PeekNamedPipe(that->m_hStdOutRead,chBuf,BUFSIZE,&dwBytesToRead,0,0);
  64. if( dwBytesToRead ) {
  65. bSuccess = ReadFile(that->m_hStdOutRead, chBuf, BUFSIZE, &dwBytesToRead, NULL);
  66. if (!bSuccess || dwBytesToRead == 0 || !_tcslen(chBuf))
  67. continue;
  68. that->m_ulStartTickCount = GetTickCount64();
  69. GLOBAL::WritePythonLog(that->m_szLogPath, chBuf);
  70. // 更新日志时间;
  71. if ( that->m_pCaseObj )
  72. that->m_pCaseObj->_ulStartTickCount = GetTickCount64();
  73. memset(chBuf, 0, BUFSIZE);
  74. }
  75. Sleep(5);
  76. } while (!that->m_bStopLogExport);
  77. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("脚本标准输出日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
  78. return 0;
  79. }
  80. DWORD CPythonExecutor::_StderrLogExportThread(LPVOID lpParam)
  81. {
  82. CPythonExecutor* that = (CPythonExecutor*)lpParam;
  83. DWORD dwRead;
  84. CHAR chBuf[BUFSIZE] = {0};
  85. CHAR szMsg[BUFSIZE+MAX_PATH] = {0};
  86. BOOL bSuccess = FALSE;
  87. do
  88. {
  89. // 预览管道中数据,有才ReadFile;
  90. PeekNamedPipe(that->m_hStdErrorRead,chBuf,BUFSIZE,&dwRead,0,0);
  91. if( dwRead ) {
  92. bSuccess = ReadFile(that->m_hStdErrorRead, chBuf, BUFSIZE, &dwRead, NULL);
  93. if (!bSuccess || dwRead == 0 || !_tcslen(chBuf))
  94. continue;
  95. GLOBAL::WritePythonLog(that->m_szLogPath, chBuf);
  96. // 脚本结果异常;
  97. that->m_pCaseObj->_nExecutionResult = SATHTTP::ABNORMAL;
  98. _stprintf_s(szMsg, "_StderrLogExportThread: 脚本出现异常, 内容=%s\n", chBuf);
  99. OutputDebugString(szMsg);
  100. memset(chBuf, 0, BUFSIZE);
  101. }
  102. Sleep(5);
  103. } while (!that->m_bStopLogExport);
  104. // 结束重定向;
  105. that->EndSubprocessStdOut();
  106. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("脚本标准错误日志线程结束,用例名=%s"), that->m_pCaseObj->strCaseName.c_str());
  107. return 0;
  108. }
  109. int CPythonExecutor::RedirectSubprocessStdout(LPSTARTUPINFO si /*=NULL*/)
  110. {
  111. // Python脚本中,必须使用sys.__stdout__()
  112. SECURITY_ATTRIBUTES sa;
  113. sa.bInheritHandle = TRUE;
  114. sa.lpSecurityDescriptor = NULL;
  115. sa.nLength = sizeof(sa);
  116. // 创建stdout的管道;
  117. if (!CreatePipe(&m_hStdOutRead, &m_hStdOutWrite, &sa, 0)) {
  118. OutputDebugString("Error:创建stdout管道失败\n");
  119. return -1;
  120. }
  121. #if 0// 标准输出和标准错误都由同一个句柄重定向,此时只需要一个线程来读取管道内容;
  122. // 创建stderr的管道,由于stderr一般就是stdout,直接复制句柄;
  123. if (!DuplicateHandle(GetCurrentProcess(), m_hStdOutWrite, GetCurrentProcess(), &m_hStdErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
  124. OutputDebugString("创建stderr管道失败\n");
  125. return -2;
  126. }
  127. #else
  128. // 标准输出和标准错误分开,需要二个线程来读取管道内容;
  129. if (!CreatePipe(&m_hStdErrorRead, &m_hStdErrorWrite, &sa, 0)) {
  130. OutputDebugString("Error:创建stderr管道失败\n");
  131. return -1;
  132. }
  133. #endif
  134. si->dwFlags |= STARTF_USESTDHANDLES;
  135. // 将子进程的stdout输出到句柄hStdOutWrite;
  136. si->hStdOutput = m_hStdOutWrite;
  137. // 将子进程的stderr输出到句柄hStdErrWrite;
  138. si->hStdError = m_hStdErrorWrite;
  139. return 0;
  140. }
  141. int CPythonExecutor::RunScriptProcess()
  142. {
  143. if (!PathFileExists(m_szScriptPath)) {
  144. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】脚本路径无效:%s", m_szScriptPath);
  145. return -1;
  146. }
  147. // 初始化参数;
  148. ::memset(&m_si, 0, sizeof(m_si));
  149. ::memset(&m_pi, 0, sizeof(m_pi));
  150. m_si.cb = sizeof(m_si);
  151. GetStartupInfo(&m_si);
  152. // 强制stdion, stdout和stderr完全无缓冲:python -u
  153. TCHAR szCommandLine[MAX_PATH] = { 0 };
  154. if (_tcslen(m_szExtraSentence))
  155. _stprintf_s(szCommandLine, _T("python -W ignore -u \"%s\" \"%s\""), m_szScriptPath, m_szExtraSentence);
  156. else
  157. _stprintf_s(szCommandLine, _T("python -W ignore -u \"%s\""), m_szScriptPath);
  158. // 重定向输出;
  159. RedirectSubprocessStdout(&m_si);
  160. // 恢复日志线程;
  161. ResumeThread(m_hStdoutLogThread);
  162. ResumeThread(m_hStderrLogThread);
  163. // 启动子进程;
  164. if (!CreateProcess(
  165. NULL, // No module name (use command line)
  166. szCommandLine, // Command line
  167. NULL, // Process handle not inheritable
  168. NULL, // Thread handle not inheritable
  169. TRUE, // Set handle inheritance to TRUE
  170. 0, // No creation flags
  171. NULL, // Use parent's environment block
  172. NULL, // Use parent's starting directory
  173. &m_si, // Pointer to STARTUPINFO structure
  174. &m_pi) // Pointer to PROCESS_INFORMATION structure
  175. )
  176. {
  177. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】创建子进程失败 (%d),", GetLastError());
  178. return -3;
  179. }
  180. // 记录进程ID;
  181. if ( m_pCaseObj )
  182. m_pCaseObj->__dwPythonPID = m_pi.dwProcessId;
  183. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "Python进程ID=%ld", m_pi.dwProcessId);
  184. // 等待进程完成退出.
  185. WaitForSingleObject(m_pi.hProcess, INFINITE);
  186. // 必须等待,等待管道输出结果;
  187. Sleep(6000);
  188. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "脚本进程结束(%ld)", m_pi.dwProcessId);
  189. // 关闭管道前,先取消管道的IO操作;
  190. CancelIo(m_hStdOutWrite);
  191. CancelIo(m_hStdErrorWrite);
  192. // 同时需要关闭输出的管道,否则ReadFile会阻塞;
  193. CloseHandle(m_hStdOutWrite);
  194. m_hStdOutWrite = NULL;
  195. CloseHandle(m_hStdErrorWrite);
  196. m_hStdErrorWrite = NULL;
  197. // 关闭进程句柄.
  198. CloseHandle(m_pi.hProcess);
  199. CloseHandle(m_pi.hThread);
  200. // 重置;
  201. memset(&m_si, 0, sizeof(m_si));
  202. memset(&m_pi, 0, sizeof(m_pi));
  203. m_si.cb = sizeof(m_si);
  204. return 0;
  205. }
  206. int CPythonExecutor::ServiceRunScriptProcess()
  207. {
  208. if (!PathFileExists(m_szScriptPath)) {
  209. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】脚本路径无效:%s", m_szScriptPath);
  210. return -1;
  211. }
  212. DWORD dwProcesses = 0;
  213. BOOL bResult = FALSE;
  214. DWORD dwRet = 0;
  215. DWORD dwSid = GetActiveSessionID();
  216. //DWORD dwSid2 = WTSGetActiveConsoleSessionId();
  217. HANDLE hProcess = NULL, hPToken = NULL, hUserTokenDup = NULL;
  218. if (!WTSQueryUserToken(dwSid, &hPToken)) {
  219. PROCESSENTRY32 procEntry;
  220. DWORD dwPid = 0;
  221. HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  222. if (hSnap == INVALID_HANDLE_VALUE) {
  223. return FALSE;
  224. }
  225. procEntry.dwSize = sizeof(PROCESSENTRY32);
  226. if (Process32First(hSnap, &procEntry)) {
  227. do {
  228. if (_tcsicmp(procEntry.szExeFile, _T("explorer.exe")) == 0) {
  229. DWORD exeSessionId = 0;
  230. if (ProcessIdToSessionId(procEntry.th32ProcessID, &exeSessionId) && exeSessionId == dwSid) {
  231. dwPid = procEntry.th32ProcessID;
  232. break;
  233. }
  234. }
  235. } while (Process32Next(hSnap, &procEntry));
  236. }
  237. CloseHandle(hSnap);
  238. // explorer进程不存在
  239. if (dwPid == 0) {
  240. return FALSE;
  241. }
  242. hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
  243. if (hProcess == NULL) {
  244. return FALSE;
  245. }
  246. if(!::OpenProcessToken(hProcess, TOKEN_ALL_ACCESS_P,&hPToken)) {
  247. CloseHandle(hProcess);
  248. return FALSE;
  249. }
  250. }
  251. if (hPToken == NULL)
  252. return -1;
  253. /*if ( !ImpersonateLoggedOnUser(hPToken) )
  254. {
  255. printf("模拟当前用户登录失败\n");
  256. }*/
  257. TOKEN_LINKED_TOKEN admin;
  258. bResult = GetTokenInformation(hPToken, (TOKEN_INFORMATION_CLASS)19, &admin, sizeof(TOKEN_LINKED_TOKEN), &dwRet);
  259. if (!bResult) {// vista 以前版本不支持TokenLinkedToken
  260. TOKEN_PRIVILEGES tp;
  261. LUID luid;
  262. if (LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid)) {
  263. tp.PrivilegeCount =1;
  264. tp.Privileges[0].Luid =luid;
  265. tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
  266. }
  267. DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
  268. } else {
  269. hUserTokenDup = admin.LinkedToken;
  270. }
  271. LPVOID pEnv =NULL;
  272. DWORD dwCreationFlags = CREATE_PRESERVE_CODE_AUTHZ_LEVEL;
  273. if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
  274. {
  275. dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
  276. }
  277. else
  278. {
  279. pEnv = NULL;
  280. }
  281. ZeroMemory( &m_si, sizeof(m_si) );
  282. m_si.cb = sizeof(m_si);
  283. m_si.dwFlags = STARTF_USESHOWWINDOW;
  284. m_si.wShowWindow = SW_HIDE;
  285. ZeroMemory( &m_pi, sizeof(m_pi) );
  286. // 重定向输出;
  287. RedirectSubprocessStdout(&m_si);
  288. // 恢复日志线程;
  289. ResumeThread(m_hStdoutLogThread);
  290. ResumeThread(m_hStderrLogThread);
  291. // 强制stdion, stdout和stderr完全无缓冲:python -u
  292. TCHAR szCommandLine[MAX_PATH] = { 0 };
  293. if (_tcslen(m_szExtraSentence))
  294. _stprintf_s(szCommandLine, _T("python -W ignore -u \"%s\" \"%s\""), m_szScriptPath, m_szExtraSentence);
  295. else
  296. _stprintf_s(szCommandLine, _T("python -W ignore -u \"%s\""), m_szScriptPath);
  297. bResult = CreateProcessAsUser(
  298. hUserTokenDup, // client's access token
  299. NULL, // file to execute
  300. szCommandLine, // command line
  301. NULL, // pointer to process SECURITY_ATTRIBUTES
  302. NULL, // pointer to thread SECURITY_ATTRIBUTES
  303. TRUE, // handles are not inheritable
  304. dwCreationFlags, // creation flags
  305. pEnv, // pointer to new environment block
  306. NULL, // name of current directory
  307. &m_si, // pointer to STARTUPINFO structure
  308. &m_pi // receives information about new process
  309. );
  310. if ( !bResult )
  311. return -1;
  312. // 记录进程ID;
  313. if ( m_pCaseObj )
  314. m_pCaseObj->__dwPythonPID = m_pi.dwProcessId;
  315. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "Python进程ID=%ld", m_pi.dwProcessId);
  316. // 等待进程完成退出.
  317. WaitForSingleObject(m_pi.hProcess, INFINITE);
  318. // 必须等待,等待管道输出结果;
  319. Sleep(6000);
  320. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "脚本进程结束(%ld)", m_pi.dwProcessId);
  321. // 关闭进程句柄.
  322. CloseHandle(m_pi.hProcess);
  323. CloseHandle(m_pi.hThread);
  324. // 关闭管道前,先取消管道的IO操作;
  325. CancelIo(m_hStdOutWrite);
  326. CancelIo(m_hStdErrorWrite);
  327. // 同时需要关闭输出的管道,否则ReadFile会阻塞;
  328. CloseHandle(m_hStdOutWrite);
  329. m_hStdOutWrite = NULL;
  330. CloseHandle(m_hStdErrorWrite);
  331. m_hStdErrorWrite = NULL;
  332. // 重置;
  333. memset(&m_si, 0, sizeof(m_si));
  334. memset(&m_pi, 0, sizeof(m_pi));
  335. m_si.cb = sizeof(m_si);
  336. if (hUserTokenDup != NULL)
  337. CloseHandle(hUserTokenDup);
  338. if (hProcess != NULL)
  339. CloseHandle(hProcess);
  340. if (hPToken != NULL)
  341. CloseHandle(hPToken);
  342. if (pEnv != NULL)
  343. DestroyEnvironmentBlock(pEnv);
  344. return TRUE;
  345. }
  346. bool CPythonExecutor::StartThread()
  347. {
  348. // 脚本进程运行线程;
  349. m_hWorkThread = CreateThread(NULL, 0, _WorkerThread, this, 0, NULL);
  350. if (!m_hWorkThread) {
  351. printf("Error:创建执行线程失败\n");
  352. return false;
  353. }
  354. // 标准输出重定向线程;
  355. m_hStdoutLogThread = CreateThread(NULL, 0, _StdoutLogExportThread, this, CREATE_SUSPENDED, NULL);
  356. if (!m_hStdoutLogThread) {
  357. printf("Error:创建日志线程失败\n");
  358. return false;
  359. }
  360. // 标准错误重定向线程;
  361. m_hStderrLogThread = CreateThread(NULL, 0, _StderrLogExportThread, this, CREATE_SUSPENDED, NULL);
  362. if (!m_hStderrLogThread) {
  363. printf("Error:创建日志线程失败\n");
  364. return false;
  365. }
  366. return true;
  367. }
  368. void CPythonExecutor::EndWorkThread()
  369. {
  370. // 结束进程;
  371. EndSubprocess();
  372. // 等待3秒,是否能自主结束线程;
  373. if (m_hWorkThread) {
  374. if (WaitForSingleObject(m_hWorkThread, 3000) == WAIT_OBJECT_0) {
  375. CloseHandle(m_hWorkThread);
  376. m_hWorkThread = NULL;
  377. return;
  378. }
  379. }
  380. // 手动结束线程;
  381. if ( m_hWorkThread ) {
  382. // 尝试5次结束行为;
  383. for (int i = 0; i < 5; i++) {
  384. if (TerminateThread(m_hWorkThread, 0))
  385. break;
  386. }
  387. CloseHandle(m_hWorkThread);
  388. m_hWorkThread = NULL;
  389. }
  390. }
  391. void CPythonExecutor::EndLogThread()
  392. {
  393. // 标记结束;
  394. m_bStopLogExport = TRUE;
  395. Sleep(20); // 等待关闭线程完成一次循环并退出;
  396. // 同时关闭重定向的句柄;
  397. EndSubprocessStdOut();
  398. // 等待5秒,是否能自主结束线程;
  399. if ( m_hStdoutLogThread ) {
  400. if ( WaitForSingleObject(m_hStdoutLogThread, 5000) == WAIT_OBJECT_0 ) {
  401. CloseHandle(m_hStdoutLogThread);
  402. m_hStdoutLogThread = NULL;
  403. }
  404. }
  405. // 手动结束线程;
  406. if (m_hStdoutLogThread) {
  407. TerminateThread(m_hStdoutLogThread, 0);
  408. // 异步结束,需要等待(5秒)系统完成操作;
  409. if ( WaitForSingleObject(m_hStdoutLogThread, 5000) == WAIT_OBJECT_0 ) {
  410. CloseHandle(m_hStdoutLogThread);
  411. m_hStdoutLogThread = NULL;
  412. }
  413. else
  414. {
  415. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束标准输出日志线程失败"));
  416. }
  417. }
  418. //////////////////////////////////////////////////////////////////////////
  419. if ( m_hStderrLogThread ) {
  420. if ( WaitForSingleObject(m_hStderrLogThread, 5000) == WAIT_OBJECT_0 ) {
  421. CloseHandle(m_hStderrLogThread);
  422. m_hStderrLogThread = NULL;
  423. }
  424. }
  425. // 手动结束线程;
  426. if (m_hStderrLogThread) {
  427. TerminateThread(m_hStderrLogThread, 0);
  428. // 异步结束,需要等待(5秒)系统完成操作;
  429. if ( WaitForSingleObject(m_hStderrLogThread, 5000) == WAIT_OBJECT_0 ) {
  430. CloseHandle(m_hStderrLogThread);
  431. m_hStderrLogThread = NULL;
  432. }
  433. else
  434. {
  435. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束标准错误日志线程失败"));
  436. }
  437. }
  438. }
  439. void CPythonExecutor::EndThread()
  440. {
  441. // 先关闭日志线程;
  442. EndLogThread();
  443. // 再关闭脚本线程;
  444. EndWorkThread();
  445. }
  446. BOOL CPythonExecutor::EndSubprocess()
  447. {
  448. // 注意TerminateProcess是异步的;
  449. TerminateProcess(m_pi.hProcess, 0);
  450. // 异步结束,需要等待(5秒)系统完成操作;
  451. if ( WaitForSingleObject(m_pi.hProcess, 5000) == WAIT_OBJECT_0 ) {
  452. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束进程(%ld)成功"), m_pi.dwProcessId);
  453. return true;
  454. }
  455. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束进程(%ld)失败"), m_pi.dwProcessId);
  456. return false;
  457. }
  458. void CPythonExecutor::EndSubprocessStdOut()
  459. {
  460. OutputDebugString("关闭重定向子进程标准输出管道句柄\n");
  461. // 关闭重定向句柄;
  462. if (m_hStdErrorRead)
  463. CloseHandle(m_hStdErrorRead);
  464. m_hStdErrorRead = NULL;
  465. if (m_hStdErrorWrite)
  466. CloseHandle(m_hStdErrorWrite);
  467. m_hStdErrorWrite = NULL;
  468. // 只有子进程方式才关闭句柄;
  469. if ( m_hStdOutWrite)
  470. CloseHandle(m_hStdOutWrite);
  471. m_hStdOutWrite = NULL;
  472. if (m_hStdOutRead)
  473. CloseHandle(m_hStdOutRead);
  474. m_hStdOutRead = NULL;
  475. }
  476. DWORD CPythonExecutor::GetActiveSessionID()
  477. {
  478. DWORD dwSessionId = 0;
  479. PWTS_SESSION_INFO pSessionInfo = NULL;
  480. DWORD dwCount = 0;
  481. WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
  482. for(DWORD i = 0; i < dwCount; i++) {
  483. WTS_SESSION_INFO si = pSessionInfo[i];
  484. if(WTSActive == si.State) {
  485. dwSessionId = si.SessionId;
  486. break;
  487. }
  488. }
  489. WTSFreeMemory(pSessionInfo);
  490. return dwSessionId;
  491. }
  492. bool CPythonExecutor::InitScript(std::string strScript, std::string strLogPath, std::string strScriptCmd)
  493. {
  494. // 判断脚本是否存在;
  495. if (!PathFileExists(strScript.c_str())) {
  496. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】脚本文件不存在:%s\n", strScript.c_str());
  497. return false;
  498. }
  499. // 判断日志文件路径是否可创建;
  500. if (!PathFileExists(strLogPath.c_str())) {
  501. // 创建路径;
  502. if (!GLOBAL::MKDIR(strLogPath.c_str())) {
  503. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】创建目录失败:%s\n", strLogPath.c_str());
  504. return false;
  505. }
  506. // 创建文件;
  507. std::ofstream flog(strLogPath.c_str());
  508. if ( flog.bad() ) {
  509. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】创建文件失败:%ld,%s\n", GetLastError(), strLogPath.c_str());
  510. return false;
  511. }
  512. flog.close();
  513. }
  514. // 赋值参数;
  515. _tcscpy_s(m_szScriptPath, strScript.c_str());
  516. _tcscpy_s(m_szLogPath, strLogPath.c_str());
  517. _tcscpy_s(m_szExtraSentence, strScriptCmd.c_str());
  518. return true;
  519. }
  520. bool CPythonExecutor::StartScript()
  521. {
  522. if (StartThread()) {
  523. Sleep(100);
  524. return true;
  525. }
  526. return false;
  527. }
  528. void CPythonExecutor::StopScript()
  529. {
  530. // 如果是子进程运行脚本,停止线程时kill进程;
  531. EndSubprocess();
  532. // 结束线程;
  533. EndWorkThread();
  534. }
  535. bool CPythonExecutor::IsScriptOver()
  536. {
  537. if ( WaitForSingleObject(m_hStdoutLogThread, 0) == WAIT_OBJECT_0 &&
  538. WaitForSingleObject(m_hStderrLogThread, 0) == WAIT_OBJECT_0 &&
  539. WaitForSingleObject(m_hWorkThread, 0) == WAIT_OBJECT_0)
  540. {
  541. // 标记任务完成;
  542. m_pCaseObj->_nExecutionState = SATHTTP::EXECUTED;
  543. // 如果任务结果为空,标记成功;
  544. if ( m_pCaseObj->_nExecutionResult == SATHTTP::NONE )
  545. m_pCaseObj->_nExecutionResult = SATHTTP::SUCCESS;
  546. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("====>脚本(%s)已完成"), m_pCaseObj->strCaseName.c_str());
  547. return true;
  548. }
  549. return false;
  550. }