PythonExecutor.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  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. #ifdef _DEBUG
  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. HANDLE hProcess = NULL, hPToken = NULL, hUserTokenDup = NULL;
  217. if (!WTSQueryUserToken(dwSid, &hPToken)) {
  218. PROCESSENTRY32 procEntry;
  219. DWORD dwPid = 0;
  220. HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  221. if (hSnap == INVALID_HANDLE_VALUE) {
  222. return FALSE;
  223. }
  224. procEntry.dwSize = sizeof(PROCESSENTRY32);
  225. if (Process32First(hSnap, &procEntry)) {
  226. do {
  227. if (_tcsicmp(procEntry.szExeFile, _T("explorer.exe")) == 0) {
  228. DWORD exeSessionId = 0;
  229. if (ProcessIdToSessionId(procEntry.th32ProcessID, &exeSessionId) && exeSessionId == dwSid) {
  230. dwPid = procEntry.th32ProcessID;
  231. break;
  232. }
  233. }
  234. } while (Process32Next(hSnap, &procEntry));
  235. }
  236. CloseHandle(hSnap);
  237. // explorer进程不存在
  238. if (dwPid == 0) {
  239. return FALSE;
  240. }
  241. hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
  242. if (hProcess == NULL) {
  243. return FALSE;
  244. }
  245. if(!::OpenProcessToken(hProcess, TOKEN_ALL_ACCESS_P,&hPToken)) {
  246. CloseHandle(hProcess);
  247. return FALSE;
  248. }
  249. }
  250. if (hPToken == NULL)
  251. return -1;
  252. TOKEN_LINKED_TOKEN admin;
  253. bResult = GetTokenInformation(hPToken, (TOKEN_INFORMATION_CLASS)19, &admin, sizeof(TOKEN_LINKED_TOKEN), &dwRet);
  254. if (!bResult) {// vista 以前版本不支持TokenLinkedToken
  255. TOKEN_PRIVILEGES tp;
  256. LUID luid;
  257. if (LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid)) {
  258. tp.PrivilegeCount =1;
  259. tp.Privileges[0].Luid =luid;
  260. tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
  261. }
  262. DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
  263. } else {
  264. hUserTokenDup = admin.LinkedToken;
  265. }
  266. LPVOID pEnv =NULL;
  267. DWORD dwCreationFlags = CREATE_PRESERVE_CODE_AUTHZ_LEVEL;
  268. if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
  269. {
  270. dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
  271. }
  272. else
  273. {
  274. pEnv = NULL;
  275. }
  276. ZeroMemory( &m_si, sizeof(m_si) );
  277. m_si.cb = sizeof(m_si);
  278. m_si.dwFlags = STARTF_USESHOWWINDOW;
  279. m_si.wShowWindow = SW_HIDE;
  280. ZeroMemory( &m_pi, sizeof(m_pi) );
  281. // 重定向输出;
  282. RedirectSubprocessStdout(&m_si);
  283. // 恢复日志线程;
  284. ResumeThread(m_hStdoutLogThread);
  285. ResumeThread(m_hStderrLogThread);
  286. // 强制stdion, stdout和stderr完全无缓冲:python -u
  287. TCHAR szCommandLine[MAX_PATH] = { 0 };
  288. if (_tcslen(m_szExtraSentence))
  289. _stprintf_s(szCommandLine, _T("python -W ignore -u \"%s\" \"%s\""), m_szScriptPath, m_szExtraSentence);
  290. else
  291. _stprintf_s(szCommandLine, _T("python -W ignore -u \"%s\""), m_szScriptPath);
  292. bResult = CreateProcessAsUser(
  293. hUserTokenDup, // client's access token
  294. NULL, // file to execute
  295. szCommandLine, // command line
  296. NULL, // pointer to process SECURITY_ATTRIBUTES
  297. NULL, // pointer to thread SECURITY_ATTRIBUTES
  298. TRUE, // handles are not inheritable
  299. dwCreationFlags, // creation flags
  300. pEnv, // pointer to new environment block
  301. NULL, // name of current directory
  302. &m_si, // pointer to STARTUPINFO structure
  303. &m_pi // receives information about new process
  304. );
  305. if ( !bResult )
  306. return -1;
  307. // 记录进程ID;
  308. if ( m_pCaseObj )
  309. m_pCaseObj->__dwPythonPID = m_pi.dwProcessId;
  310. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "Python进程ID=%ld", m_pi.dwProcessId);
  311. // 等待进程完成退出.
  312. WaitForSingleObject(m_pi.hProcess, INFINITE);
  313. // 必须等待,等待管道输出结果;
  314. Sleep(6000);
  315. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "脚本进程结束(%ld)", m_pi.dwProcessId);
  316. // 关闭进程句柄.
  317. CloseHandle(m_pi.hProcess);
  318. CloseHandle(m_pi.hThread);
  319. // 关闭管道前,先取消管道的IO操作;
  320. CancelIo(m_hStdOutWrite);
  321. CancelIo(m_hStdErrorWrite);
  322. // 同时需要关闭输出的管道,否则ReadFile会阻塞;
  323. CloseHandle(m_hStdOutWrite);
  324. m_hStdOutWrite = NULL;
  325. CloseHandle(m_hStdErrorWrite);
  326. m_hStdErrorWrite = NULL;
  327. // 重置;
  328. memset(&m_si, 0, sizeof(m_si));
  329. memset(&m_pi, 0, sizeof(m_pi));
  330. m_si.cb = sizeof(m_si);
  331. if (hUserTokenDup != NULL)
  332. CloseHandle(hUserTokenDup);
  333. if (hProcess != NULL)
  334. CloseHandle(hProcess);
  335. if (hPToken != NULL)
  336. CloseHandle(hPToken);
  337. if (pEnv != NULL)
  338. DestroyEnvironmentBlock(pEnv);
  339. return TRUE;
  340. }
  341. bool CPythonExecutor::StartThread()
  342. {
  343. // 脚本进程运行线程;
  344. m_hWorkThread = CreateThread(NULL, 0, _WorkerThread, this, 0, NULL);
  345. if (!m_hWorkThread) {
  346. printf("Error:创建执行线程失败\n");
  347. return false;
  348. }
  349. // 标准输出重定向线程;
  350. m_hStdoutLogThread = CreateThread(NULL, 0, _StdoutLogExportThread, this, CREATE_SUSPENDED, NULL);
  351. if (!m_hStdoutLogThread) {
  352. printf("Error:创建日志线程失败\n");
  353. return false;
  354. }
  355. // 标准错误重定向线程;
  356. m_hStderrLogThread = CreateThread(NULL, 0, _StderrLogExportThread, this, CREATE_SUSPENDED, NULL);
  357. if (!m_hStderrLogThread) {
  358. printf("Error:创建日志线程失败\n");
  359. return false;
  360. }
  361. return true;
  362. }
  363. void CPythonExecutor::EndWorkThread()
  364. {
  365. // 结束进程;
  366. EndSubprocess();
  367. // 等待3秒,是否能自主结束线程;
  368. if (m_hWorkThread) {
  369. if (WaitForSingleObject(m_hWorkThread, 3000) == WAIT_OBJECT_0) {
  370. CloseHandle(m_hWorkThread);
  371. m_hWorkThread = NULL;
  372. return;
  373. }
  374. }
  375. // 手动结束线程;
  376. if ( m_hWorkThread ) {
  377. // 尝试5次结束行为;
  378. for (int i = 0; i < 5; i++) {
  379. if (TerminateThread(m_hWorkThread, 0))
  380. break;
  381. }
  382. CloseHandle(m_hWorkThread);
  383. m_hWorkThread = NULL;
  384. }
  385. }
  386. void CPythonExecutor::EndLogThread()
  387. {
  388. // 标记结束;
  389. m_bStopLogExport = TRUE;
  390. Sleep(20); // 等待关闭线程完成一次循环并退出;
  391. // 同时关闭重定向的句柄;
  392. EndSubprocessStdOut();
  393. // 等待5秒,是否能自主结束线程;
  394. if ( m_hStdoutLogThread ) {
  395. if ( WaitForSingleObject(m_hStdoutLogThread, 5000) == WAIT_OBJECT_0 ) {
  396. CloseHandle(m_hStdoutLogThread);
  397. m_hStdoutLogThread = NULL;
  398. }
  399. }
  400. // 手动结束线程;
  401. if (m_hStdoutLogThread) {
  402. TerminateThread(m_hStdoutLogThread, 0);
  403. // 异步结束,需要等待(5秒)系统完成操作;
  404. if ( WaitForSingleObject(m_hStdoutLogThread, 5000) == WAIT_OBJECT_0 ) {
  405. CloseHandle(m_hStdoutLogThread);
  406. m_hStdoutLogThread = NULL;
  407. }
  408. else
  409. {
  410. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束标准输出日志线程失败"));
  411. }
  412. }
  413. //////////////////////////////////////////////////////////////////////////
  414. if ( m_hStderrLogThread ) {
  415. if ( WaitForSingleObject(m_hStderrLogThread, 5000) == WAIT_OBJECT_0 ) {
  416. CloseHandle(m_hStderrLogThread);
  417. m_hStderrLogThread = NULL;
  418. }
  419. }
  420. // 手动结束线程;
  421. if (m_hStderrLogThread) {
  422. TerminateThread(m_hStderrLogThread, 0);
  423. // 异步结束,需要等待(5秒)系统完成操作;
  424. if ( WaitForSingleObject(m_hStderrLogThread, 5000) == WAIT_OBJECT_0 ) {
  425. CloseHandle(m_hStderrLogThread);
  426. m_hStderrLogThread = NULL;
  427. }
  428. else
  429. {
  430. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束标准错误日志线程失败"));
  431. }
  432. }
  433. }
  434. void CPythonExecutor::EndThread()
  435. {
  436. // 先关闭日志线程;
  437. EndLogThread();
  438. // 再关闭脚本线程;
  439. EndWorkThread();
  440. }
  441. BOOL CPythonExecutor::EndSubprocess()
  442. {
  443. // 注意TerminateProcess是异步的;
  444. TerminateProcess(m_pi.hProcess, 0);
  445. // 异步结束,需要等待(5秒)系统完成操作;
  446. if ( WaitForSingleObject(m_pi.hProcess, 5000) == WAIT_OBJECT_0 ) {
  447. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束进程(%ld)成功"), m_pi.dwProcessId);
  448. return true;
  449. }
  450. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("结束进程(%ld)失败"), m_pi.dwProcessId);
  451. return false;
  452. }
  453. void CPythonExecutor::EndSubprocessStdOut()
  454. {
  455. OutputDebugString("关闭重定向子进程标准输出管道句柄\n");
  456. // 关闭重定向句柄;
  457. if (m_hStdErrorRead)
  458. CloseHandle(m_hStdErrorRead);
  459. m_hStdErrorRead = NULL;
  460. if (m_hStdErrorWrite)
  461. CloseHandle(m_hStdErrorWrite);
  462. m_hStdErrorWrite = NULL;
  463. // 只有子进程方式才关闭句柄;
  464. if ( m_hStdOutWrite)
  465. CloseHandle(m_hStdOutWrite);
  466. m_hStdOutWrite = NULL;
  467. if (m_hStdOutRead)
  468. CloseHandle(m_hStdOutRead);
  469. m_hStdOutRead = NULL;
  470. }
  471. DWORD CPythonExecutor::GetActiveSessionID()
  472. {
  473. DWORD dwSessionId = 0;
  474. PWTS_SESSION_INFO pSessionInfo = NULL;
  475. DWORD dwCount = 0;
  476. WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
  477. for(DWORD i = 0; i < dwCount; i++) {
  478. WTS_SESSION_INFO si = pSessionInfo[i];
  479. if(WTSActive == si.State) {
  480. dwSessionId = si.SessionId;
  481. break;
  482. }
  483. }
  484. WTSFreeMemory(pSessionInfo);
  485. return dwSessionId;
  486. }
  487. bool CPythonExecutor::InitScript(std::string strScript, std::string strLogPath, std::string strScriptCmd)
  488. {
  489. // 判断脚本是否存在;
  490. if (!PathFileExists(strScript.c_str())) {
  491. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】脚本文件不存在:%s\n", strScript.c_str());
  492. return false;
  493. }
  494. // 判断日志文件路径是否可创建;
  495. if (!PathFileExists(strLogPath.c_str())) {
  496. // 创建路径;
  497. if (!GLOBAL::MKDIR(strLogPath.c_str())) {
  498. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】创建目录失败:%s\n", strLogPath.c_str());
  499. return false;
  500. }
  501. // 创建文件;
  502. std::ofstream flog(strLogPath.c_str());
  503. if ( flog.bad() ) {
  504. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, "【Error】创建文件失败:%ld,%s\n", GetLastError(), strLogPath.c_str());
  505. return false;
  506. }
  507. flog.close();
  508. }
  509. // 赋值参数;
  510. _tcscpy_s(m_szScriptPath, strScript.c_str());
  511. _tcscpy_s(m_szLogPath, strLogPath.c_str());
  512. _tcscpy_s(m_szExtraSentence, strScriptCmd.c_str());
  513. return true;
  514. }
  515. bool CPythonExecutor::StartScript()
  516. {
  517. if (StartThread()) {
  518. Sleep(100);
  519. return true;
  520. }
  521. return false;
  522. }
  523. void CPythonExecutor::StopScript()
  524. {
  525. // 如果是子进程运行脚本,停止线程时kill进程;
  526. EndSubprocess();
  527. // 结束线程;
  528. EndWorkThread();
  529. }
  530. bool CPythonExecutor::IsScriptOver()
  531. {
  532. if ( WaitForSingleObject(m_hStdoutLogThread, 0) == WAIT_OBJECT_0 &&
  533. WaitForSingleObject(m_hStderrLogThread, 0) == WAIT_OBJECT_0 &&
  534. WaitForSingleObject(m_hWorkThread, 0) == WAIT_OBJECT_0)
  535. {
  536. // 标记任务完成;
  537. m_pCaseObj->_nExecutionState = SATHTTP::EXECUTED;
  538. // 如果任务结果为空,标记成功;
  539. if ( m_pCaseObj->_nExecutionResult == SATHTTP::NONE )
  540. m_pCaseObj->_nExecutionResult = SATHTTP::SUCCESS;
  541. GLOBAL::WriteTextLog(GLOBAL::SAT_PYE, _T("====>脚本(%s)已完成"), m_pCaseObj->strCaseName.c_str());
  542. return true;
  543. }
  544. return false;
  545. }