Przeglądaj źródła

基本完成模块封装

scbc.sat2 5 lat temu
rodzic
commit
d367b73cef

+ 84 - 0
RunPython/RunPython/CritSection.h

@@ -0,0 +1,84 @@
+#ifndef __CRITSECTION_20160221__
+#define __CRITSECTION_20160221__
+
+// ÁÙ½çÖµ;
+class ThreadSection
+{
+public:
+	ThreadSection(){
+		HRESULT hr = Init();
+		(hr);
+	}
+
+	~ThreadSection(){
+		DeleteCriticalSection(&_CriticalSection);
+	}
+
+	bool Lock()
+	{
+		bool result = false;
+		__try
+		{
+			EnterCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+	bool Unlock()
+	{
+		bool result = false;
+		__try
+		{
+			LeaveCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+private:
+	HRESULT Init() throw()
+	{
+		HRESULT hRes = E_FAIL;
+		__try
+		{
+			InitializeCriticalSection(&_CriticalSection);
+			hRes = S_OK;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+			hRes = E_OUTOFMEMORY;
+		}
+		return hRes;
+	}
+
+	ThreadSection(const ThreadSection & tSection);
+	ThreadSection &operator=(const ThreadSection & tSection);
+	CRITICAL_SECTION _CriticalSection;
+};
+
+
+class AutoThreadSection
+{
+public:
+	AutoThreadSection(IN ThreadSection* pSection){
+		_pSection = pSection;
+		_pSection->Lock();
+	}
+
+	~AutoThreadSection(){
+		_pSection->Unlock();
+	}
+private:
+	AutoThreadSection(const AutoThreadSection & tSection);
+	AutoThreadSection &operator=(const AutoThreadSection & tSection);
+	ThreadSection * _pSection;
+};
+
+#endif //__CRITSECTION_20160221__

+ 631 - 0
RunPython/RunPython/Global.cpp

@@ -0,0 +1,631 @@
+#include "stdafx.h"
+#include "Global.h"
+#include <SetupAPI.h>
+#include <InitGuid.h>
+#include <WinIoCtl.h>
+#include <direct.h>
+#include <fcntl.h>
+#include <share.h>
+#include <sys\stat.h>
+#pragma comment(lib, "SetupAPI.lib")
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	TCHAR g_szCurModuleDir[MAX_PATH] = { 0 };
+	TCHAR g_szCurModulePath[MAX_PATH] = { 0 };
+	TCHAR g_szFna[MAX_PATH] = { 0 };
+	TCHAR g_szConfig[MAX_PATH] = { 0 };
+	TCHAR g_szLogPath[MAX_PATH] = { 0 };
+	TCHAR g_szPython27Dir[MAX_PATH] = {0};
+	TCHAR g_szTVPort[MAX_PATH] = {0};
+	TCHAR g_szTVReboot[MAX_PATH] = {0};
+	TCHAR g_szTVShutdown[MAX_PATH] = {0};
+	BOOL  g_bWatchTVPort = FALSE;
+
+	bool g_bEnableLog = false;
+	COleDateTime g_lastTime;
+	time_t g_time = time(NULL);
+	ThreadSection g_critSection;
+	FILE *gp_log_fp = NULL;
+	
+	//////////////////////////////////////////////////////////////////////////
+	bool MKDIR(LPCTSTR dir) 
+	{
+		//////////////////////////////////////////////////////////////////////////
+		// 创建目录;
+		int nleft = 0;
+		int nIndex = -1;
+		string strdir = dir;
+		strdir = strdir.substr(0, strdir.find_last_of(_T("\\")));
+
+		if (strdir.at(strdir.size() - 1) != _T('\\'))
+			strdir.append(_T("\\"));
+
+		// 共享路径和硬盘盘符;
+		if (_tcscmp(strdir.substr(0, 2).c_str(), _T("\\\\")) == 0)
+			nleft = strdir.find_first_of(_T("\\"), 2) + 1;	// 去除共享主机名;
+		else if (strdir.at(2) == _T('\\'))
+			nleft = 3;
+
+		do
+		{
+			nIndex = strdir.substr(nleft, -1).find_first_of(_T("\\"));
+
+			if (nIndex != string::npos)
+			{
+				if (_mkdir(strdir.substr(0, nIndex + nleft).c_str()) == -1 && (errno != EEXIST))
+				{
+					WriteTextLog(_T("创建目录失败:%s,错误码:%d"), strdir.substr(0, nIndex + nleft).c_str(), errno);
+					return false;
+				}
+
+				nleft += nIndex + 1;
+			}
+		} while (nIndex != -1);
+
+		return true;
+	};
+
+	// 全局函数;
+	/************************************************************************/
+	/*  函数:WriteTextLog[7/28/2009 Jeff];
+	/*  描述:写文本日志;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WriteTextLog(const TCHAR* format, ...)
+	{
+		static ThreadSection _critSection;
+		AutoThreadSection aSection(&_critSection);
+		// 将日志内容输入到文件中;
+		// 获取今年年份;
+		__time64_t gmt = time(NULL); // 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		struct tm gmtm = { 0 };
+		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = { 0 };
+		_stprintf_s(szlogpath, _T("%srunner-log %02d%02d.txt"), g_szCurModuleDir, gmtm.tm_mon + 1, gmtm.tm_mday);
+		// 打开或创建文件;
+		FILE* fp = NULL;
+		//MKDIR(g_szLogPath);
+		//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+		if (_access(szlogpath, 0) != -1)
+#else
+		if (_taccess(szlogpath, 0) != -1)
+#endif
+		{ // 存在;
+			if (0 == _tfopen_s(&fp, szlogpath, _T("a+")))
+				// 移动到末尾;
+				fseek(fp, 0, SEEK_END);
+		}
+		else
+		{ // 不存在;
+			_tfopen_s(&fp, szlogpath, _T("w+"));
+		}
+
+		if (fp == NULL)
+			return;
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs")); //设定中文;
+
+		// 格式化日志内容;
+		va_list args = NULL;
+		int len = 0;
+		TCHAR* buffer = NULL;
+		va_start(args, format);
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf(format, args) + 1;
+		buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+		_vstprintf_s(buffer, len, format, args);
+		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free(buffer);
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale); //还原区域设定;
+	}
+
+	void WritePythonLog(LPCTSTR file, const TCHAR* msg)
+	{
+		AutoThreadSection aSection(&g_critSection);
+		// 将日志内容输入到文件中;
+		// 获取今年年份;
+		//__time64_t gmt = time(NULL); // 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		//struct tm gmtm = { 0 };
+		//localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+
+		int nErr = -1;
+		// 打开或创建文件;
+		FILE* fp = NULL;
+		
+#ifndef UNICODE
+		if (_access(file, 0) != -1)
+#else
+		if (_taccess(file, 0) != -1)
+#endif
+		{ // 存在;
+			if (0 == _tfopen_s(&fp, file, _T("a+")))
+			{
+				// 移动到末尾;
+				fseek(fp, 0, SEEK_END);
+			}
+			else
+			{
+				WriteTextLog(_T("打开文件失败:%s,%d"), file, GetLastError());
+				return;
+			}
+		}
+		else
+		{ // 不存在;
+			MKDIR(file);
+			if (0 !=  _tfopen_s(&fp, file, _T("w+")) )
+			{
+				WriteTextLog(_T("创建文件失败:%s,%d"), file, GetLastError());
+				return;
+			}
+		}
+
+		if (fp == NULL)
+		{
+			WriteTextLog(_T("文件句柄空:%s,%d"), file, GetLastError());
+			return;
+		}
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs")); //设定中文;
+		//_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, msg);
+		_ftprintf(fp,,msg);
+		// 关闭文件,释放资源并设置回原语言区域;
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale); //还原区域设定;
+	}
+
+	// 从注册表获取 Python27路径;
+	BOOL Python27Dir(LPTSTR lpPython27Dir, int nBufferLen)
+	{
+		HKEY hKey;
+		int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\WOW6432Node\\Python\\PythonCore\\2.7\\InstallPath"), 0, KEY_QUERY_VALUE, &hKey);
+		if (ret != ERROR_SUCCESS)
+			return FALSE;
+
+		//读取KEY
+		DWORD dwType = REG_SZ; //数据类型
+		DWORD cbData = nBufferLen;
+		ret = RegQueryValueEx(hKey, _T(""), NULL, &dwType, (LPBYTE)lpPython27Dir, &cbData);
+		if (ret != ERROR_SUCCESS)
+		{
+			RegCloseKey(hKey);
+			return FALSE;
+		}
+		RegCloseKey(hKey);
+
+		return TRUE;
+	}
+
+	void ClosePythonLog()
+	{
+		AutoThreadSection aSection(&g_critSection);
+		if ( gp_log_fp )
+		{
+			WriteTextLog(_T("关闭文件:%s"), g_szLogPath);
+			fclose(gp_log_fp);
+			gp_log_fp = NULL;
+		}
+	}
+
+	// 去除空格;
+	std::string& trim(std::string& str)
+	{
+		int nIndex = 0;
+		while ((nIndex = str.find_first_of(' ')) != std::string::npos)
+			str.erase(nIndex, 1);
+
+		return str;
+	}
+
+	// hModule 模块句柄 NULL表示当前模块;
+	bool GetVersion(IN const TCHAR* fname, OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion)
+	{
+		VS_FIXEDFILEINFO* pVi = NULL;
+		DWORD dwHandle = 0;
+		int size = GetFileVersionInfoSize(fname, &dwHandle);
+		if (size > 0)
+		{
+			BYTE* buffer = new BYTE[size];
+			memset(buffer, 0, size);
+
+			if (GetFileVersionInfo(fname, 0, size, buffer))
+			{
+				if (VerQueryValue(buffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& size))
+				{
+					pdwFileVersion[0] = HIWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[1] = LOWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[2] = HIWORD(pVi->dwFileVersionLS);
+					pdwFileVersion[3] = LOWORD(pVi->dwFileVersionLS);
+
+					pdwProductVerion[0] = HIWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[1] = LOWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[2] = HIWORD(pVi->dwProductVersionLS);
+					pdwProductVerion[3] = LOWORD(pVi->dwProductVersionLS);
+
+					delete[] buffer;
+					return true;
+				}
+			}
+
+			delete[] buffer;
+		}
+
+		return false;
+	}
+
+	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4])
+	{
+		TCHAR fname[MAX_PATH];
+		VS_FIXEDFILEINFO* pVi;
+		DWORD dwHandle;
+
+		if (GetModuleFileName(hModule, fname, MAX_PATH))
+		{
+			INT nSize = GetFileVersionInfoSize(fname, &dwHandle);
+
+			if (nSize > 0)
+			{
+				BYTE* pBuffer = new BYTE[nSize];
+				memset(pBuffer, 0, nSize);
+
+				if (GetFileVersionInfo(fname, 0, nSize, pBuffer))
+				{
+					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& nSize))
+					{
+						dwFVArray[0] = HIWORD(pVi->dwFileVersionMS);
+						dwFVArray[1] = LOWORD(pVi->dwFileVersionMS);
+						dwFVArray[2] = HIWORD(pVi->dwFileVersionLS);
+						dwFVArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+						dwPVArray[0] = HIWORD(pVi->dwProductVersionMS);
+						dwPVArray[1] = LOWORD(pVi->dwProductVersionMS);
+						dwPVArray[2] = HIWORD(pVi->dwProductVersionLS);
+						dwPVArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+						delete[]pBuffer;
+						return TRUE;
+					}
+				}
+
+				if (pBuffer)
+					delete[]pBuffer;
+			}
+		}
+
+		return FALSE;
+	}
+
+	WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr)
+	{
+		if (lpASCIIStr == NULL)
+			return NULL;
+
+		// 获取宽字符字节数;
+		int cchWideChar = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+		if (cchWideChar == 0)
+			return NULL;
+
+		// 转换成宽字符串;
+		WCHAR* pWideChar = new WCHAR[cchWideChar + 1];
+		memset(pWideChar, 0, sizeof(WCHAR) * (cchWideChar + 1));
+		int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pWideChar, cchWideChar);
+		if (nWriteNum != cchWideChar)
+		{
+			if (pWideChar)
+				delete[] pWideChar;
+			return NULL;
+		}
+
+		return pWideChar;
+	}
+
+	BOOL UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT string& strResult)
+	{
+		if (lpUNICODEStr == NULL)
+			return FALSE;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0)
+			return FALSE;
+
+		// 转换成多字节字符;
+		CHAR* pResult = new CHAR[cbMultiByte];
+		memset(pResult, 0, cbMultiByte);
+		int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pResult, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+			return FALSE;
+
+		strResult = pResult;
+		if (pResult)
+			delete[] pResult;
+
+		return TRUE;
+	}
+
+	BOOL ASCII2UTF8(IN LPCCH lpASCIIStr, OUT string& strResult)
+	{
+		// 将ASCII字符串转成UNICODE字符串;
+		WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+		if (pWideChar == NULL)
+			return FALSE;
+
+		// 再将UICODE转成UTF8;
+		BOOL bResult = UNICODE2UTF8(pWideChar, strResult);
+
+		if (pWideChar)
+			delete[] pWideChar;
+
+		return bResult;
+	}
+
+	string EnCode_UTF8URL(IN const CHAR* pText)
+	{
+		string tt = "";
+		string dd = "";
+		ASCII2UTF8(pText, tt);
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				dd.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				dd.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				dd.append(tempbuff);
+			}
+		}
+		return dd;
+	}
+
+	void EnCode_UTF8URL(IN const CHAR* pText, OUT string& strResult)
+	{
+		string tt = "";
+		ASCII2UTF8(pText, tt);
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				strResult.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				strResult.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				strResult.append(tempbuff);
+			}
+		}
+	}
+
+	//做为解Url使用
+	char CharToInt(char ch)
+	{
+		if (ch >= '0' && ch <= '9')return (char)(ch - '0');
+		if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
+		if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
+		return -1;
+	}
+
+	char StrToBin(IN char(&str)[2])
+	{
+		char tempWord[2];
+		char chn;
+
+		tempWord[0] = CharToInt(str[0]);                         //make the B to 11 -- 00001011
+		tempWord[1] = CharToInt(str[1]);                         //make the 0 to 0  -- 00000000
+
+		chn = (tempWord[0] << 4) | tempWord[1];                //to change the BO to 10110000
+
+		return chn;
+	}
+
+	CHAR* UNICODE2ASCII(IN LPWCH lpUNICODEStr)
+	{
+		if (lpUNICODEStr == NULL)
+			return NULL;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0)
+			return NULL;
+
+		// 转换成多字节字符;
+		CHAR *pMultiByteStr = new CHAR[cbMultiByte + 1];
+		memset(pMultiByteStr, 0, cbMultiByte + 1);
+		int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+		{
+			if (pMultiByteStr)
+				delete[]pMultiByteStr;
+			return NULL;
+		}
+
+		pMultiByteStr[cbMultiByte] = '\0';
+
+		return pMultiByteStr;
+	}
+
+	BOOL UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen)
+	{
+		if (lpUNICODEStr == NULL)
+			return FALSE;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0 || cbMultiByte >= nASCIIStrLen)
+			return FALSE;
+
+		// 转换成多字节字符;
+		memset((void*)pASCIIStr, 0, nASCIIStrLen);
+		int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pASCIIStr, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+		{
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	/************************************************************************/
+	/*  函数:[7/26/2016 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	string DeCode_URLUNICODE(IN const CHAR* pURLText)
+	{
+		string str = pURLText;
+		string strResult = "";
+
+		INT nIndex = 0;
+		string strTemp = "";
+
+		while (str.find("\\u", 0, 2) != string::npos)
+		{
+			nIndex = str.find("\\u", 0, 2);
+			strResult.append(str.substr(0, nIndex));
+			strTemp = str.substr(nIndex + 2, 4);
+			str = str.substr(nIndex + 2 + 4);
+			CHAR szReturn[10] = { 0 };
+
+			union  __UNION_VAR_INT {
+				BYTE   ch[2];
+				int	   value;
+			}unionVarInt;
+
+			unionVarInt.ch[0] = (CharToInt(strTemp.at(2)) << 4) | (CharToInt(strTemp.at(3)) & 0x00FF);
+			unionVarInt.ch[1] = (CharToInt(strTemp.at(0)) << 4) | (CharToInt(strTemp.at(1)) & 0x00FF);
+
+			WCHAR szWide[2] = { 0 };
+			szWide[0] = unionVarInt.value;
+			UNICODE2ASCII(szWide, szReturn, 10);
+			strResult.append(szReturn);
+		}
+		strResult.append(str);
+
+		return strResult;
+	}
+
+	// 通过注册表查找系统当前串口信息;
+	
+	BOOL IsValidString(LPCTSTR lpszString)
+	{
+		if (lpszString == NULL)
+			return FALSE;
+
+		do
+		{
+			// ASCII可显示的字符;
+			if (*lpszString < 32 || *lpszString > 126)
+			{
+				return FALSE;
+			}
+		} while (*++lpszString);
+
+		return TRUE;
+	}
+
+	BOOL Python27Dir()
+	{
+		HKEY hKey;
+		int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\WOW6432Node\\Python\\PythonCore\\2.7\\InstallPath"), 0, KEY_QUERY_VALUE, &hKey);
+		if (ret != ERROR_SUCCESS)
+			return FALSE;
+
+		//读取KEY
+		DWORD dwType = REG_SZ; //数据类型
+		DWORD cbData = MAX_PATH;
+		ret = RegQueryValueEx(hKey, _T(""), NULL, &dwType, (LPBYTE)g_szPython27Dir, &cbData);
+		if (ret != ERROR_SUCCESS)
+		{
+			RegCloseKey(hKey);
+			return FALSE;
+		}
+		RegCloseKey(hKey);
+
+		return TRUE;
+	}
+
+	void GetResourceCfg()
+	{
+		// 配置文件;
+		Python27Dir();
+		TCHAR szConfig[MAX_PATH] = {0};
+		_stprintf_s(szConfig, _T("%sLib\\site-packages\\ssat_sdk\\config\\resource_run.cfg"), g_szPython27Dir);
+
+		// 电视串口号;
+		GetPrivateProfileString(_T("COMM"), _T("serial_communicator_port"), NULL, g_szTVPort, MAX_PATH, szConfig);
+		// 重启关键字;
+		g_bWatchTVPort = GetPrivateProfileInt(_T("Abnormal"), _T("Watch"), 0, szConfig);
+		// 重启关键字;
+		GetPrivateProfileString(_T("Abnormal"), _T("reboot"), NULL, g_szTVReboot, MAX_PATH, szConfig);
+		// 关机关键字;
+		GetPrivateProfileString(_T("Abnormal"), _T("shutdown"), NULL, g_szTVShutdown, MAX_PATH, szConfig);
+	}
+
+	void Split(std::string str1, std::string str2, std::vector<std::string> &vt)
+	{
+		if ( str1.size() == 0 || str2.size() == 0 )
+			return;
+
+		int npos = str1.find(str2);
+		while( std::string::npos != npos )
+		{
+			vt.push_back(str1.substr(0, npos));
+			str1 = str1.substr(npos + str2.size());
+			npos = str1.find(str2);
+		}
+
+		if ( str1.size() )
+			vt.push_back(str1);
+	}
+} // namespace Global

+ 49 - 0
RunPython/RunPython/Global.h

@@ -0,0 +1,49 @@
+
+#pragma once
+#include <stdio.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h> //或者 #include <ctime>
+#include <io.h>
+#pragma comment(lib,"version.lib")
+#include <vector>
+#include <string>
+using namespace std;
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	extern TCHAR g_szCurModuleDir[MAX_PATH];
+	extern TCHAR g_szCurModulePath[MAX_PATH];
+	extern TCHAR g_szFna[MAX_PATH];
+	extern TCHAR g_szConfig[MAX_PATH];
+	extern TCHAR g_szPython27Dir[MAX_PATH];
+	extern TCHAR g_szTVPort[MAX_PATH];
+	extern TCHAR g_szTVReboot[MAX_PATH];
+	extern TCHAR g_szTVShutdown[MAX_PATH];
+	extern BOOL  g_bWatchTVPort;
+
+	extern bool g_bEnableLog;
+	extern TCHAR g_szLogPath[MAX_PATH];
+	extern COleDateTime g_lastTime;
+	extern time_t g_time;
+	extern FILE *gp_log_fp;
+
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	bool GetVersion(IN const TCHAR *fname, OUT WORD *pdwFileVersion, OUT WORD *pdwProductVerion);
+	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4]);
+	void WriteTextLog(const TCHAR *format, ...);
+	void WritePythonLog(LPCTSTR file, const TCHAR* msg);
+	void ClosePythonLog();
+	std::string EnCode_UTF8URL(IN const CHAR* pText);
+	std::string &trim(std::string &str);
+	bool MKDIR(LPCTSTR dir);
+	// 字符串是否由数字、字母、符号组成;
+	BOOL IsValidString(LPCTSTR lpszString);
+	string DeCode_URLUNICODE(IN const CHAR* pURLText);
+	BOOL Python27Dir();
+	void GetResourceCfg();
+	void Split(std::string str1, std::string str2, std::vector<std::string> &vt);
+};

+ 14 - 6
RunPython/RunPython/RunPython.cpp

@@ -3,6 +3,7 @@
 
 #include "stdafx.h"
 #include "RunPython.h"
+#include "ScriptExecutor.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -33,12 +34,18 @@ int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 		// TODO: 在此处为应用程序的行为编写代码。
 		//RunPython("E:\\bin\\ScbcCopyKey\\test.py"); // 加载失败,但改成test2.py后,就能加载成功
 		//RunPythonEx("E:\\bin\\ScbcCopyKey\\ScbcTest.py", NULL);
-		RunPythonEx("D:\\SAT\\runner\\btc_runner_se\\runner\\output\\ODF_NPI_RT2841\\20191119172310094\\192.168.1.119_5555\\cases\\RT_2841\\ODF_NPI_RT2841\\picture\\22.py", NULL);
+		//RunPythonEx("D:\\SAT\\runner\\btc_runner_se\\runner\\output\\ODF_NPI_RT2841\\20191119172310094\\192.168.1.119_5555\\cases\\RT_2841\\ODF_NPI_RT2841\\picture\\22.py", NULL);
 		//Sleep(10000);
-		printf("\n\n\n\n=================================================================\n\n");
+		//printf("\n\n\n\n=================================================================\n\n");
 		//CallPythonEx("D:\\SAT\\runner\\btc_runner_se\\runner\\output\\ODF_NPI_RT2841\\20191119172310094\\192.168.1.119_5555\\cases\\RT_2841\\ODF_NPI_RT2841\\picture\\22.py", NULL);
 		//CallPythonEx("E:\\bin\\ScbcCopyKey\\ScbcTest.py", NULL);
-		printf("\n\n\n\n=================================================================\n\n");
+		//printf("\n\n\n\n=================================================================\n\n");
+#if 1
+		CScriptExecutor excutor;
+		excutor.InitScript("E:\\bin\\ScbcCopyKey\\ScbcTest.py", "D:\\SAT\\log.txt", "", PY_RUN_TYPE::SUBPROCESS);
+		excutor.StartScript();
+		system("pause");
+#endif
 	}
 
 	system("pause");
@@ -412,12 +419,12 @@ RUNPYTHON_API int CallPython(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
 // 读出stdout  
 BOOL ReadFromPipe(HANDLE hStdOutRead)  
 {  
-	char out_buffer[4096];  
+	char out_buffer[BUFSIZE] = {0};  
 	DWORD dwRead;    
 	BOOL bSuccess = FALSE;  
 
 	//用WriteFile,从hStdOutRead读出子进程stdout输出的数据,数据结果在out_buffer中,长度为dwRead  
-	bSuccess = ReadFile( hStdOutRead, out_buffer, 4096, &dwRead, NULL);  
+	bSuccess = ReadFile( hStdOutRead, out_buffer, BUFSIZE, &dwRead, NULL);  
 	if ((bSuccess) && (dwRead!=0))  //如果成功了,且长度>0  
 	{  
 		// 此处加入你自己的代码  
@@ -552,7 +559,8 @@ RUNPYTHON_API int CallPythonEx(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
 	while (GetExitCodeProcess(pi.hProcess, &process_exit_code))
 	{
 		// 读取stdout、stderr;
-		GetOutput(hStdOutRead, 3000);
+		//GetOutput(hStdOutRead, 3000);
+		ReadFromPipe(hStdOutRead);
 		if ( process_exit_code != STILL_ACTIVE )
 			break;
 	}

+ 12 - 0
RunPython/RunPython/RunPython.vcproj

@@ -249,6 +249,10 @@
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
+			<File
+				RelativePath=".\Global.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\PythonHelper.cpp"
 				>
@@ -295,6 +299,14 @@
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
+			<File
+				RelativePath=".\CritSection.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Global.h"
+				>
+			</File>
 			<File
 				RelativePath=".\PythonHelper.h"
 				>

+ 3 - 0
RunPython/RunPython/RunPython.vcxproj

@@ -129,6 +129,7 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="Global.cpp" />
     <ClCompile Include="PythonHelper.cpp" />
     <ClCompile Include="RunPython.cpp" />
     <ClCompile Include="ScriptExecutor.cpp" />
@@ -139,6 +140,8 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="CritSection.h" />
+    <ClInclude Include="Global.h" />
     <ClInclude Include="PythonHelper.h" />
     <ClInclude Include="Resource.h" />
     <ClInclude Include="RunPython.h" />

+ 9 - 0
RunPython/RunPython/RunPython.vcxproj.filters

@@ -27,6 +27,9 @@
     <ClCompile Include="stdafx.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="Global.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="PythonHelper.h">
@@ -47,6 +50,12 @@
     <ClInclude Include="targetver.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="CritSection.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Global.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="RunPython.rc">

+ 301 - 49
RunPython/RunPython/ScriptExecutor.cpp

@@ -1,8 +1,29 @@
 #include "StdAfx.h"
 #include "ScriptExecutor.h"
+#include <fstream>
 
 CScriptExecutor::CScriptExecutor(void)
 {
+	m_hWorkThread = NULL;
+	m_hWorkEvent = NULL;
+	m_hLogThread = NULL;
+	m_hLogEvent = NULL;
+	m_bStatus = FALSE;
+	m_nRunType = 0;
+	m_hStdOutRead = NULL;
+	m_hStdOutWrite = NULL;
+	m_hStdErrorWrite = 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;
 }
 
 CScriptExecutor::~CScriptExecutor(void)
@@ -11,35 +32,105 @@ CScriptExecutor::~CScriptExecutor(void)
 
 DWORD __stdcall CScriptExecutor::_WorkerThread(LPVOID lpParam)
 {
+	CScriptExecutor* that = (CScriptExecutor*)lpParam;
+	if ( !that )
+	{
+		printf("Error:参数失效\n");
+		return -1;
+	}
+
+	if ( that->m_nRunType == PY_RUN_TYPE::EMBEDDED )
+	{
+		that->RunEmbeddedScript();
+	}
+	else if (that->m_nRunType == PY_RUN_TYPE::SUBPROCESS)
+	{
+		that->RunScripProcess();
+	}
+
+	// 线程结束后,应该回调一个通知函数;
+	// ...
+
 	return 0;
 }
 
-int CScriptExecutor::RedirectStdout(STARTUPINFO &si)
+DWORD __stdcall CScriptExecutor::_LogExportThread(LPVOID lpParam)
 {
-	SECURITY_ATTRIBUTES sa;
-	sa.bInheritHandle = TRUE;
-	sa.lpSecurityDescriptor = NULL;
-	sa.nLength = sizeof(sa);
-
-	// 创建stdout的管道;
-	if (!CreatePipe(&m_hStdOutRead, &m_hStdOutWrite, &sa, 0))
+	CScriptExecutor* that = (CScriptExecutor*)lpParam;
+	if (!that)
 	{
-		printf("Error:创建stdout管道失败\n");
+		printf("Error:参数失效\n");
 		return -1;
 	}
 
-	// 创建stderr的管道,由于stderr一般就是stdout,直接复制句柄;
-	if (!DuplicateHandle(GetCurrentProcess(), m_hStdOutWrite, GetCurrentProcess(), &m_hStdErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS))
+	if (that->m_nRunType == PY_RUN_TYPE::SUBPROCESS)
 	{
-		printf("创建stderr管道失败\n");
-		return -2;
+		DWORD dwRead, dwWritten;
+		CHAR chBuf[BUFSIZE] = {0};
+		BOOL bSuccess = FALSE;
+		HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+
+		for (;;)
+		{
+			if (that->m_hStdOutRead)
+				break;
+			Sleep(100);
+		}
+		
+		do
+		{
+			bSuccess = ReadFile(that->m_hStdOutRead, chBuf, BUFSIZE, &dwRead, NULL);
+			if (!bSuccess || dwRead == 0) 
+				continue;
+
+			Global::WritePythonLog(that->m_szLogPath, chBuf);
+			memset(chBuf, 0, BUFSIZE);
+		} while (!that->m_bStopLogExport);
 	}
 
-	si.dwFlags |= STARTF_USESTDHANDLES;
-	// 将子进程的stdout输出到句柄hStdOutWrite;
-	si.hStdOutput = m_hStdOutWrite;
-	// 将子进程的stderr输出到句柄hStdErrWrite;
-	si.hStdError = m_hStdErrorWrite;
+	return 0;
+}
+
+int CScriptExecutor::RedirectStdout(STARTUPINFO& si)
+{
+	if (m_nRunType == PY_RUN_TYPE::SUBPROCESS)
+	{
+		SECURITY_ATTRIBUTES sa;
+		sa.bInheritHandle = TRUE;
+		sa.lpSecurityDescriptor = NULL;
+		sa.nLength = sizeof(sa);
+
+		// 创建stdout的管道;
+		if (!CreatePipe(&m_hStdOutRead, &m_hStdOutWrite, &sa, 0))
+		{
+			printf("Error:创建stdout管道失败\n");
+			return -1;
+		}
+
+		// 创建stderr的管道,由于stderr一般就是stdout,直接复制句柄;
+		if (!DuplicateHandle(GetCurrentProcess(), m_hStdOutWrite, GetCurrentProcess(), &m_hStdErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS))
+		{
+			printf("创建stderr管道失败\n");
+			return -2;
+		}
+
+		si.dwFlags |= STARTF_USESTDHANDLES;
+		// 将子进程的stdout输出到句柄hStdOutWrite;
+		si.hStdOutput = m_hStdOutWrite;
+		// 将子进程的stderr输出到句柄hStdErrWrite;
+		si.hStdError = m_hStdErrorWrite;
+
+		return 0;
+	}
+	else if (m_nRunType == PY_RUN_TYPE::EMBEDDED)
+	{
+		return -1;
+	}
+
+	// 异常类型;
+	printf("Error:异常类型\n");
+
+	return -5;
 }
 
 void CScriptExecutor::CatchPythonException()
@@ -83,7 +174,7 @@ void CScriptExecutor::CatchPythonException()
 					printf("Error:导入traceback模块失败\n");
 					return;
 				}
-#if 1
+#if 1 // 细分出所有换行符;
 				PyObject* pPyModuleDict = PyModule_GetDict(pPyTraceModule);
 				if (pPyModuleDict)
 				{
@@ -220,26 +311,15 @@ int CScriptExecutor::RunScripProcess()
 {
 	if (!PathFileExists(m_szScriptPath))
 	{
-		printf("参数无效\n");
+		printf("Error:脚本路径无效\n");
 		return -1;
 	}
 
-	// 获取Python27进程目录;
-	TCHAR szPython27Dir[MAX_PATH] = { 0 };
-	TCHAR szPython27Exe[MAX_PATH] = { 0 };
-	if (!Python27Dir(szPython27Dir, MAX_PATH))
-	{
-		printf("获取Python27目录失败\n");
-		return -2;
-	}
-	_stprintf_s(szPython27Exe, _T("%spython.exe"), szPython27Dir);
-
-	STARTUPINFO si;
-	::memset(&si, 0, sizeof(si));
-	si.cb = sizeof(si);
-
-	PROCESS_INFORMATION pi;
-	::memset(&pi, 0, sizeof(pi));
+	// 初始化参数;
+	::memset(&m_si, 0, sizeof(m_si));
+	::memset(&m_pi, 0, sizeof(m_pi));
+	m_si.cb = sizeof(m_si);
+	GetStartupInfo(&m_si); 
 
 	TCHAR szCommandLine[MAX_PATH] = { 0 };
 	if (_tcslen(m_szExtraSentence))
@@ -247,45 +327,217 @@ int CScriptExecutor::RunScripProcess()
 	else
 		_stprintf_s(szCommandLine, _T("python -W ignore %s"), m_szScriptPath);
 
+	// 重定向输出;
+	RedirectStdout(m_si);
+	// 恢复日志线程;
+	ResumeThread(m_hLogThread);
+
 	// 启动子进程;
 	if (!CreateProcess(
-		NULL,			// No module name (use command line)
+		NULL,					// No module name (use command line)
 		szCommandLine,			// Command line
 		NULL,					// Process handle not inheritable
 		NULL,					// Thread handle not inheritable
-		FALSE,					// Set handle inheritance to TRUE
+		TRUE,					// Set handle inheritance to TRUE
 		0,						// No creation flags
 		NULL,					// Use parent's environment block
 		NULL,					// Use parent's starting directory 
-		&si,					// Pointer to STARTUPINFO structure
-		&pi)					// Pointer to PROCESS_INFORMATION structure
+		&m_si,					// Pointer to STARTUPINFO structure
+		&m_pi)					// Pointer to PROCESS_INFORMATION structure
 		)
 	{
-		printf("CreateProcess failed (%d).\n", GetLastError());
+		printf("Error:创建子进程失败 (%d).\n", GetLastError());
 		return -3;
 	}
 
-	// Wait until child process exits.
-	WaitForSingleObject(pi.hProcess, INFINITE);
+	// 等待进程完成退出.
+	WaitForSingleObject(m_pi.hProcess, INFINITE);
+	// 结束日志线程;
+	m_bStopLogExport = TRUE;
 
-	// Close process and thread handles. 
-	CloseHandle(pi.hProcess);
-	CloseHandle(pi.hThread);
+	// 关闭进程句柄. 
+	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;
 }
 
-void CScriptExecutor::InitScript(std::string strScript, std::string strLogPath, std::string strScriptCmd, int nRunType)
+bool CScriptExecutor::StartWorkThread()
+{
+	// 创建线程;
+	m_hWorkThread = CreateThread(NULL, 0, _WorkerThread, this, 0, NULL);
+	if (!m_hWorkThread)
+	{
+		printf("Error:创建线程失败\n");
+		return false;
+	}
+
+	return true;
+}
+
+bool CScriptExecutor::StartLogThread()
+{
+	// 创建线程事件:手动控制,无信号状态;
+	m_hLogEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if (!m_hLogEvent)
+	{
+		printf("Error:无法为线程创建控制事件\n");
+		return false;
+	}
+
+	// 创建线程;
+	m_hLogThread = CreateThread(NULL, 0, _LogExportThread, this, CREATE_SUSPENDED, NULL);
+	if (!m_hLogThread)
+	{
+		printf("Error:创建线程失败\n");
+		CloseHandle(m_hLogEvent);
+		m_hLogEvent = NULL;
+
+		return false;
+	}
+
+	return true;
+}
+
+void CScriptExecutor::EndWorkThread()
+{
+	// 等待线程结束;
+	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()
+{
+	// 设置事件有信号;
+	if (m_hLogEvent)
+		SetEvent(m_hLogEvent);
+
+	// 等待线程结束;
+	if (m_hLogThread)
+	{
+		WaitForSingleObject(m_hLogThread, INFINITE);
+		CloseHandle(m_hLogThread);
+		m_hLogThread = NULL;
+	}
+
+	// 关闭句柄;
+	if (m_hLogEvent)
+		CloseHandle(m_hLogEvent);
+	m_hLogEvent = NULL;
+}
+
+void CScriptExecutor::EndThread(HANDLE hThread, HANDLE hEvent)
 {
+	// 设置事件有信号;
+	if (hEvent)
+		SetEvent(hEvent);
+
+	// 等待线程结束;
+	if (hThread)
+	{
+		WaitForSingleObject(hThread, INFINITE);
+		CloseHandle(hThread);
+		hThread = NULL;
+	}
 
+	// 关闭句柄;
+	if (hEvent)
+		CloseHandle(hEvent);
+	hEvent = NULL;
+}
+
+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::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;
+	}
+
+	// 判断日志文件路径是否可创建;
+	if (!PathFileExists(strLogPath.c_str()))
+	{
+		// 创建路径;
+		if (!Global::MKDIR(strLogPath.c_str()))
+		{
+			printf("Error:创建目录失败\n");
+			return;
+		}
+
+		// 创建文件;
+		std::ofstream flog(strLogPath.c_str());
+		if ( flog.bad() )
+		{
+			printf("Error:创建文件失败\n");
+			return;
+		}
+		flog.close();
+	}
+
+	// 赋值参数;
+	m_nRunType = nRunType;
+	_tcscpy_s(m_szScriptPath, strScript.c_str());
+	_tcscpy_s(m_szLogPath, strLogPath.c_str());
+	_tcscpy_s(m_szExtraSentence, strScriptCmd.c_str());
 }
 
 bool CScriptExecutor::StartScript()
 {
+	if (StartWorkThread())
+	{
+		// 开启日志导出线程;
+		if (!StartLogThread())
+		{
+			printf("Error:日志导出线程创建出错\n");
+		}
+
+		return true;
+	}
+
+	// 异常类型;
+	printf("Error:异常类型脚本\n");
+
 	return false;
 }
 
-bool CScriptExecutor::StopScript()
+void CScriptExecutor::StopScript()
 {
-	return false;
+	// 如果是子进程运行脚本,停止线程时kill进程;
+	if (m_nRunType == PY_RUN_TYPE::SUBPROCESS)
+		EndSubprocess();
+
+	// 结束线程;
+	EndWorkThread();
 }

+ 42 - 10
RunPython/RunPython/ScriptExecutor.h

@@ -3,6 +3,13 @@
 
 #pragma once
 
+#define BUFSIZE 4096
+enum PY_RUN_TYPE
+{
+	EMBEDDED,			// 嵌入到本进程运行;
+	SUBPROCESS			// 以子进程方式运行;
+};
+
 class CScriptExecutor
 {
 public:
@@ -10,21 +17,31 @@ public:
 	~CScriptExecutor(void);
 
 protected:
-	HANDLE			m_hThread;						// 事件句柄;
-	HANDLE			m_hEvent;						// 线程事件;
-	BOOL			m_bStatus;						// 线程状态;
-	TCHAR			m_szScriptPath[MAX_PATH];		// 脚本路径;
-	TCHAR			m_szLogPath[MAX_PATH];			// 日志路径;	
-	TCHAR			m_szExtraSentence[MAX_PATH];	// 脚本命令行参数;
+	HANDLE			m_hWorkThread;						// 事件句柄;
+	HANDLE			m_hWorkEvent;						// 线程事件;
+	HANDLE			m_hLogThread;						// 事件句柄;
+	HANDLE			m_hLogEvent;						// 线程事件;
+	BOOL			m_bStatus;							// 线程状态;
+	TCHAR			m_szScriptPath[MAX_PATH];			// 脚本路径;
+	TCHAR			m_szLogPath[MAX_PATH];				// 日志路径;	
+	TCHAR			m_szExtraSentence[MAX_PATH];		// 脚本命令行参数或额外要执行的语句;
 	int				m_nRunType;
 	// 重定向标准输出和标准错误;
 	HANDLE			m_hStdOutRead;
 	HANDLE			m_hStdOutWrite;
 	HANDLE			m_hStdErrorWrite;
-
+	// 子进程信息;
+	STARTUPINFO			m_si;
+	PROCESS_INFORMATION	m_pi;
+	// 进程结束标志;
+	BOOL			m_bKillProcess;
+	// 停止日志导出线程;
+	BOOL			m_bStopLogExport;
 protected:
 	// 工作者线程函数;
 	static DWORD WINAPI _WorkerThread(LPVOID lpParam);
+	// 日志导出线程;
+	static DWORD WINAPI _LogExportThread(LPVOID lpParam);
 	// 重定向标准输出;
 	int RedirectStdout(STARTUPINFO& si);
 	// 获取Python异常;
@@ -33,13 +50,28 @@ protected:
 	int RunEmbeddedScript();
 	// 运行脚本进程;
 	int RunScripProcess();
-	
+	// 开启线程;
+	bool StartWorkThread();
+	bool StartLogThread();
+	// 结束线程;
+	void EndWorkThread();
+	void EndLogThread();
+	void EndThread(HANDLE hThread, HANDLE hEvent);
+	// 结束子进程;
+	bool EndSubprocess();
+	// 从管道读取日志;
+	void ReadFromPipe();
 public:
-	void InitScript(std::string strScript, std::string strLogPath, std::string strScriptCmd, int nRunType = 0);
+	// 初始脚本运行参数;
+	void InitScript(
+		std::string strScript, 
+		std::string strLogPath, 
+		std::string strScriptCmd, 
+		int nRunType = PY_RUN_TYPE::EMBEDDED);
 	// 运行脚本;
 	bool StartScript();
 	// 停止脚本;
-	bool StopScript();
+	void StopScript();
 };
 
 #endif // __SCRIPT_EXECUTOR__

+ 2 - 1
RunPython/RunPython/stdafx.h

@@ -29,7 +29,8 @@
 #include <windows.h>
 #include <string>
 #include <Shlwapi.h>
-
+#include "CritSection.h"
+#include "Global.h"
 #include "Python.h"
 
 // TODO: 在此处引用程序需要的其他头文件