Quellcode durchsuchen

添加TV串口监听库:用于U盘强制升级。

sat23 vor 4 Jahren
Ursprung
Commit
c1dd0a6427

+ 20 - 0
SerialWatch/SerialWatch.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SerialWatch", "SerialWatch\SerialWatch.vcproj", "{4319EFC1-51BB-4000-933B-6EA7BBEA3B97}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{4319EFC1-51BB-4000-933B-6EA7BBEA3B97}.Debug|Win32.ActiveCfg = Debug|Win32
+		{4319EFC1-51BB-4000-933B-6EA7BBEA3B97}.Debug|Win32.Build.0 = Debug|Win32
+		{4319EFC1-51BB-4000-933B-6EA7BBEA3B97}.Release|Win32.ActiveCfg = Release|Win32
+		{4319EFC1-51BB-4000-933B-6EA7BBEA3B97}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 84 - 0
SerialWatch/SerialWatch/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__

+ 1471 - 0
SerialWatch/SerialWatch/Global.cpp

@@ -0,0 +1,1471 @@
+#pragma once
+
+#include "stdafx.h"
+#include "Global.h"
+#include <io.h>
+#include <direct.h>
+#include <tlhelp32.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+#include <WinVer.h>		
+#pragma comment(lib,"version.lib")
+#include "CritSection.h"
+// 获取本机ip地址;
+#include <Iphlpapi.h>  
+#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库 
+
+// 获取网卡地址;
+#include <SetupAPI.h>
+#include <InitGuid.h>
+#include <WinIoCtl.h>
+#pragma comment(lib, "SetupAPI.lib")
+
+
+namespace GLOBAL
+{
+	PyNotice g_PyNotify;
+	STSATConfig g_stSATConfig;
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	TCHAR g_szIniFile[MAX_PATH] = {0};
+	TCHAR g_szHostName[MAX_PATH] = {0};			// 主机计算机名;
+	TCHAR g_szConnectString[MAX_PATH];			// DB连接串;
+
+	TCHAR g_szCurModuleFileName[MAX_PATH] = { 0 };			// 软件名称;
+	TCHAR g_szCurModuleDir[MAX_PATH] = { 0 };
+	TCHAR g_szCurModulePath[MAX_PATH] = { 0 };
+	TCHAR g_szFna[_MAX_FNAME] = { 0 };
+	TCHAR g_szExt[_MAX_EXT] = { 0 };
+
+	// 服务器信息;
+	TCHAR g_szDBSource[MAX_PATH];				// 数据库源(服务所在IP或计算机名);
+	TCHAR g_szDBSourcePort[MAX_PATH];			// 数据库源端口;
+	DWORD g_dwDBServerPort;						// 数据库源端口;
+	TCHAR g_szDBAccount[MAX_PATH];				// 数据库登录用户;
+	TCHAR g_szDBPassWord[MAX_PATH];				// 数据库登录密码;
+	TCHAR g_szDBName[MAX_PATH];					// 数据库名称;	
+	TCHAR g_szPython27Dir[MAX_PATH] = {0};
+	TCHAR g_szPython27ResourceConfig[MAX_PATH] = { 0 };
+	std::string g_strIPAddress;
+
+	//////////////////////////////////////////////////////////////////////////
+	std::string g_strMacs;
+	std::vector<MacAddress> g_vtMac;
+
+	// usb;
+	static GUID UsbClassGuid = { 0xA5DCBF10L, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
+	// mac;
+	static GUID MacClassGuid = { 0xAD498944, 0x762F, 0x11D0, {0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C} };
+	// hdd;
+	static GUID HDDClassGuid = { 0x53F56307, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B} };
+	//////////////////////////////////////////////////////////////////////////
+
+	ThreadSection g_critSection;
+	ThreadSection g_csTextLog;
+	//////////////////////////////////////////////////////////////////////////
+	static const int BEGIN_YEAR = 1901;
+	static const int NUMBER_YEAR = 199;
+	static const unsigned int LUNAR_YEARS[199] =
+	{
+		0x04AE53, 0x0A5748, 0x5526BD, 0x0D2650, 0x0D9544, 0x46AAB9, 0x056A4D, 0x09AD42, 0x24AEB6, 0x04AE4A, //1901-1910
+		0x6A4DBE, 0x0A4D52, 0x0D2546, 0x5D52BA, 0x0B544E, 0x0D6A43, 0x296D37, 0x095B4B, 0x749BC1, 0x049754, //1911-1920
+		0x0A4B48, 0x5B25BC, 0x06A550, 0x06D445, 0x4ADAB8, 0x02B64D, 0x095742, 0x2497B7, 0x04974A, 0x664B3E, //1921-1930
+		0x0D4A51, 0x0EA546, 0x56D4BA, 0x05AD4E, 0x02B644, 0x393738, 0x092E4B, 0x7C96BF, 0x0C9553, 0x0D4A48, //1931-1940
+		0x6DA53B, 0x0B554F, 0x056A45, 0x4AADB9, 0x025D4D, 0x092D42, 0x2C95B6, 0x0A954A, 0x7B4ABD, 0x06CA51, //1941-1950
+		0x0B5546, 0x555ABB, 0x04DA4E, 0x0A5B43, 0x352BB8, 0x052B4C, 0x8A953F, 0x0E9552, 0x06AA48, 0x7AD53C, //1951-1960
+		0x0AB54F, 0x04B645, 0x4A5739, 0x0A574D, 0x052642, 0x3E9335, 0x0D9549, 0x75AABE, 0x056A51, 0x096D46, //1961-1970
+		0x54AEBB, 0x04AD4F, 0x0A4D43, 0x4D26B7, 0x0D254B, 0x8D52BF, 0x0B5452, 0x0B6A47, 0x696D3C, 0x095B50, //1971-1980
+		0x049B45, 0x4A4BB9, 0x0A4B4D, 0xAB25C2, 0x06A554, 0x06D449, 0x6ADA3D, 0x0AB651, 0x093746, 0x5497BB, //1981-1990
+		0x04974F, 0x064B44, 0x36A537, 0x0EA54A, 0x86B2BF, 0x05AC53, 0x0AB647, 0x5936BC, 0x092E50, 0x0C9645, //1991-2000
+		0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, 0x0A954E, //2001-2010
+		0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, 0x474AB9, //2011-2020
+		0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x69573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, 0x05AA43, //2021-2030
+		0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, 0x0B5A4C, //2031-2040
+		0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, 0x355B37, //2041-2050
+		0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06B244, 0x4AB638, 0x0AAE4C, 0x092E42, //2051-2060
+		0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, 0x052D4B, //2061-2070
+		0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, 0x3A93B6, //2071-2080
+		0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, 0x8E933E, //2081-2090
+		0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5 //2091-2099
+	};
+
+	//////////////////////////////////////////////////////////////////////////
+	BOOL IsValidDate(IN LPCTSTR lpDate)	// 判断公历;
+	{
+		if (lpDate == NULL || _tcscmp(lpDate, _T("")) == 0)
+			return FALSE;
+
+		CString strDate = lpDate;
+		if (strDate.IsEmpty()) return FALSE;
+
+		// 判断日期合法性;
+		static int nYear = 0;
+		static int nMonth = 0;
+		static int nDay = 0;
+
+		nYear = nMonth = nDay = 0;
+		nYear = _ttoi(strDate.Left(4));
+
+		nMonth = _ttoi(strDate.Mid(5, 2));
+		nDay = _ttoi(strDate.Mid(8, 2));
+
+		CONST static INT nNormalMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+		CONST static INT nLeapMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+		if ((nDay <= 0) || (nDay > 31) || (nMonth <= 0) || (nMonth > 12)) return FALSE;
+
+		if ((nYear % 400 == 0) || (nYear % 4 == 0 && nYear % 100 != 0))
+		{
+			if (nDay > nLeapMonth[nMonth - 1])	return FALSE;
+		}
+		else
+		{
+			if (nDay > nNormalMonth[nMonth - 1]) return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	BOOL IsValidLunanrDate(IN LPCTSTR lpDate)	// 判断农历;
+	{
+		if (lpDate == NULL || _tcscmp(lpDate, _T("")) == 0)
+			return FALSE;
+
+		CString strDate = lpDate;
+		if (strDate.IsEmpty()) return FALSE;
+
+		static int lunar_year, lunar_month, lunar_day;
+		lunar_year = lunar_month = lunar_day = 0;
+
+		lunar_year = _ttoi(strDate.Left(4));
+		lunar_month = _ttoi(strDate.Mid(5, 2));
+		lunar_day = _ttoi(strDate.Mid(8, 2));
+
+		//越界检查,如果越界,返回无效日期;
+		if (lunar_year <= BEGIN_YEAR || lunar_year > BEGIN_YEAR + NUMBER_YEAR - 1)
+			return FALSE;
+
+		if (lunar_month < 1 || lunar_month > 12)
+			return FALSE;
+
+		// 1.农历年是否有闰月;
+		int nYearIndex = lunar_year - BEGIN_YEAR;
+		int leap_month = (LUNAR_YEARS[nYearIndex] >> 20) & 0xF;
+
+		// 2.月份大小月天数;
+		int month_day = 0;
+		if ((LUNAR_YEARS[nYearIndex] >> (7 + 13 - lunar_month)) & 0x1)
+			month_day = 30;
+		else
+			month_day = 29;
+
+		if (lunar_day < 0 || lunar_day > month_day)
+			return FALSE;
+
+		return TRUE;
+	}
+
+	int GetIniInfo(IN const TCHAR *szPath , const TCHAR *szIniName )
+	{
+		Python27Dir();
+		TCHAR szDrive[_MAX_DRIVE] = { 0 };
+		TCHAR szDir[_MAX_DIR] = { 0 };
+		TCHAR szFna[_MAX_FNAME] = { 0 };
+		TCHAR szExt[_MAX_EXT] = { 0 };
+		DWORD dwRet = ::GetModuleFileName(NULL, g_szCurModuleFileName, sizeof(g_szCurModuleFileName) / sizeof(TCHAR));
+
+		_tsplitpath_s(g_szCurModuleFileName, szDrive, szDir, g_szFna, g_szExt);
+		StringCchCat(g_szCurModuleDir, MAX_PATH, szDrive);
+		StringCchCat(g_szCurModuleDir, MAX_PATH, szDir);
+
+		// -----------------------------------------------------//
+		TCHAR szIniPath[MAX_PATH] = {0};
+		if (szPath != NULL && szIniName != NULL)
+			StringCchPrintf(szIniPath, MAX_PATH, _T("%s%s"), szPath, szIniName);
+		else
+			StringCchPrintf(szIniPath, MAX_PATH, _T("%sSATService.ini"), g_szCurModuleDir);
+
+		HANDLE hFile = CreateFile(szIniPath, 0/*GENERIC_READ*/, 0, NULL, OPEN_EXISTING, 0, NULL);
+		
+		// resoucre_run.cfg;
+		_stprintf_s(g_szPython27ResourceConfig, _T("%s%s"), g_szPython27Dir, "Lib\\site-packages\\ssat_sdk\\config\\resource_run.cfg");
+		if (ERROR_FILE_NOT_FOUND == GetLastError())
+		{
+			return -1;
+		}
+
+		// 获取服务器端信息;
+		GetPrivateProfileString(_T("SATService"), _T("ScriptDir"), _T(""), g_stSATConfig.szScriptDir, MAX_PATH, szIniPath);
+		if ( g_stSATConfig.szScriptDir[_tcslen(g_stSATConfig.szScriptDir)-1] != '\\')
+		{
+			_tcscat_s(g_stSATConfig.szScriptDir, MAX_PATH, "\\");
+			WritePrivateProfileString(_T("SATService"), _T("ScriptDir"), g_stSATConfig.szScriptDir, szIniPath);
+		}
+		// 同时将该目录写入resouce_run.cfg中;
+		WritePrivateProfileString(_T("SATService"), _T("ScriptDir"), g_stSATConfig.szScriptDir, g_szPython27ResourceConfig);
+
+		g_stSATConfig.dwAdbKillTime = GetPrivateProfileInt(_T("SATService"), _T("AdbKillTime"), 9000, szIniPath);
+		g_stSATConfig.dwAdbTimeout = GetPrivateProfileInt(_T("SATService"), _T("AdbTimeout"), 120000, szIniPath);
+		g_stSATConfig.dwTCPSvrPort = GetPrivateProfileInt(_T("SATService"), _T("TCPSvrPort"), 5588, szIniPath);
+		g_stSATConfig.dwScriptTimeout = GetPrivateProfileInt(_T("SATService"), _T("ScriptTimeout"), 300000, szIniPath);
+		GetPrivateProfileString(_T("SATService"), _T("ExecuteServer"), _T(""), g_stSATConfig.szExecuteServer, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("SATService"), _T("ExecuteSyscode"), _T(""), g_stSATConfig.szExecuteSysCode, MAX_PATH, szIniPath);
+
+		GetPrivateProfileString(_T("SATService"), _T("ApkServer"), _T(""), g_stSATConfig.szApkServer, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("SATService"), _T("ApkSyscode"), _T(""), g_stSATConfig.szApkSysCode, MAX_PATH, szIniPath);
+
+		GetPrivateProfileString(_T("SATService"), _T("CaseServer"), _T(""), g_stSATConfig.szCaseServer, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("SATService"), _T("CaseSyscode"), _T(""), g_stSATConfig.szCaseSysCode, MAX_PATH, szIniPath);
+
+		GetPrivateProfileString(_T("SATService"), _T("TaskServer"), _T(""), g_stSATConfig.szTaskServer, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("SATService"), _T("TaskSyscode"), _T(""), g_stSATConfig.szTaskSysCode, MAX_PATH, szIniPath);
+
+		GetPrivateProfileString(_T("SATService"), _T("ResultServer"), _T(""), g_stSATConfig.szResultServer, MAX_PATH, szIniPath);
+
+		GetPrivateProfileString(_T("SATService"), _T("ResultExcelDir"), _T(""), g_stSATConfig.szResultExcelDir, MAX_PATH, szIniPath);
+		
+		GetPrivateProfileString(_T("LinuxDevice"), _T("device"), _T(""), g_stSATConfig.stLinuxDevice.szDevice, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("LinuxDevice"), _T("manu"), _T(""), g_stSATConfig.stLinuxDevice.szManu, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("LinuxDevice"), _T("hardwareversion"), _T(""), g_stSATConfig.stLinuxDevice.szHardwareVersion, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("LinuxDevice"), _T("model"), _T(""), g_stSATConfig.stLinuxDevice.szModel, MAX_PATH, szIniPath);
+
+		// 读取其他目录的配置文件;sat_result_dir
+		GetPrivateProfileString(_T("COMM"), _T("serial_communicator_port"), _T(""), g_stSATConfig.szTVPort, MAX_PATH, g_szPython27ResourceConfig);
+		GetPrivateProfileString(_T("Abnormal"), _T("reboot"), NULL, g_stSATConfig.szTVReboot, MAX_PATH, g_szPython27ResourceConfig);
+		GetPrivateProfileString(_T("Abnormal"), _T("shutdown"), NULL, g_stSATConfig.szTVShutdown, MAX_PATH, g_szPython27ResourceConfig);
+		g_stSATConfig.bWatchTVPort = GetPrivateProfileInt(_T("Abnormal"), _T("Watch"), 0, g_szPython27ResourceConfig);
+		GetPrivateProfileString(_T("COMM"), _T("sat_result_dir"), _T(""), g_stSATConfig.szCaseResultDir, MAX_PATH, g_szPython27ResourceConfig);
+		// 将反斜转正斜;
+		std::string dir = Replace(g_stSATConfig.szCaseResultDir, "\\", "/");
+		_stprintf_s(g_stSATConfig.szCaseResultDir, dir.c_str());
+		if (g_stSATConfig.szCaseResultDir[_tcslen(g_stSATConfig.szCaseResultDir) - 1] != '\\')
+			_tcscat_s(g_stSATConfig.szCaseResultDir, MAX_PATH, "\\");
+
+		// 将新的SATSevice的tcp端口号复制到resource_run中;
+		TCHAR szValue[10] = { 0 };
+		_itoa_s(g_stSATConfig.dwTCPSvrPort, szValue, 10);
+		// 作用:python脚本不需要去读取SATService的配置文件;
+		WritePrivateProfileString(_T("COMM"), _T("runner_tcp_port"), szValue, g_szPython27ResourceConfig);
+
+		return 0;
+	}
+
+	// 判断指定字符串是否在数组里(区分大小写);
+	BOOL IsStringExist(IN CString& str, IN CStringArray &tagAry)
+	{
+		int nSize = tagAry.GetSize();
+		if (nSize == 0) return FALSE;
+
+		BOOL bExist = FALSE;
+		for (int i = 0; i < nSize; i++)
+		{
+			if (str == tagAry.ElementAt(i))
+			{
+				bExist = TRUE;
+				break;
+			}
+		}
+
+		return bExist;
+	}
+
+	// 判断指定字符串是否在数组里(区分大小写);
+	BOOL IsStringExist(IN TString& str, IN vector<TString> &tagVt)
+	{
+		int nSize = tagVt.size();
+		if (nSize == 0) return FALSE;
+
+		BOOL bExist = FALSE;
+		for (vector<TString>::iterator it = tagVt.begin(); it != tagVt.end(); it++)
+		{
+			if (str.compare(it->c_str()) == 0)
+			{
+				bExist = TRUE;
+				break;
+			}
+		}
+
+		return bExist;
+	}
+
+	// 判断指定字符串是否在数组里(不区分大小写);
+	BOOL IsStringExistNoCase(IN CString& str, IN CStringArray &tagAry)
+	{
+		int nSize = tagAry.GetSize();
+		if (nSize == 0) return FALSE;
+
+		BOOL bExist = FALSE;
+		for (int i = 0; i < nSize; i++)
+		{
+			if (str.CompareNoCase(tagAry.ElementAt(i)) == 0)
+			{
+				bExist = TRUE;
+				break;
+			}
+		}
+
+		return bExist;
+	}
+
+	BOOL IsStringExistNoCase(IN CONST TString& str, IN CStringArray &tagAry)
+	{
+		int nSize = tagAry.GetSize();
+		if (nSize == 0) return FALSE;
+
+		BOOL bExist = FALSE;
+		for (int i = 0; i < nSize; i++)
+		{
+			if ((tagAry.ElementAt(i).CompareNoCase(str.c_str())) == 0)
+			{
+				bExist = TRUE;
+				break;
+			}
+		}
+
+		return bExist;
+	}
+
+	// 判断指定字符串是否在数组里(不区分大小写);
+	BOOL IsStringExistNoCase(IN CONST TString& str, IN vector<TString> &tagVt)
+	{
+		int nSize = tagVt.size();
+		if (nSize == 0) return FALSE;
+
+		BOOL bExist = FALSE;
+		TString stmp1 = uppercase(str);
+		TString stmp2;
+		for (vector<TString>::iterator it = tagVt.begin(); it != tagVt.end(); it++)
+		{
+			stmp2 = uppercase(*it);
+			if (stmp1.compare(stmp2) == 0)
+			{
+				bExist = TRUE;
+				break;
+			}
+		}
+
+		return bExist;
+	}
+
+
+	TString uppercase(IN const TString &Str)
+	{
+		const TCHAR aazz = _T('z') - _T('Z');
+		TString sResult;
+		for (TString::const_iterator it = Str.begin(); Str.end() != it; it++)
+		{
+			if (_T('a') <= *it && *it <= _T('z'))
+				sResult.append(1, *it - aazz);
+			else
+				sResult.append(1, *it);
+		}
+		return sResult;
+	}
+
+	int match(IN CONST TString &sFileExt, IN CONST TString &sFile)
+	{
+		TString fext = uppercase(sFileExt);
+		TString file = uppercase(sFile);
+
+		int pos = file.find_last_of(_T('.'));
+		if (TString::npos != pos)
+			file = file.substr(pos);
+
+		return (TString::npos != fext.find(file));
+	}
+
+	TString getfilename(IN CONST TString &file)
+	{
+		TString name;
+		TString strfile = file;
+		int nIndex = strfile.find_last_of(_T('\\'));	// 如果file不包含 '\\' ,得不到文件名;
+		if (nIndex == TString::npos)
+		{
+			nIndex = strfile.find_last_of(_T('.'));
+			if ( nIndex == TString::npos )
+				return _T("");
+
+			return strfile.substr(0, nIndex);
+		}
+
+		name = strfile.substr(nIndex+1);
+		nIndex = name.find_last_of(_T('.'));
+		if (nIndex == TString::npos)
+			return _T("");
+
+		return name.substr(0, nIndex);
+	}
+
+	// 获取文件名;
+	CString getfilename(IN CONST CString &file)
+	{
+		CString name;
+		CString strfile = file;
+		int nIndex = strfile.ReverseFind(_T('\\'));	// 如果file不包含 '\\' ,得不到文件名;
+		if (nIndex == -1)
+		{
+			nIndex = strfile.ReverseFind(_T('.'));
+			if (nIndex == -1)
+				return _T("");
+
+			return strfile.Left(nIndex);
+		}
+
+		name = strfile.Mid(nIndex+1);
+		nIndex = name.Find(_T('.'));
+		if (nIndex == -1)
+			return _T("");
+
+		return name.Left(nIndex);
+	}
+
+	// 通过路径名查找进程,返回进程ID;
+	BOOL FindAppProcessID(IN CString path, OUT DWORD &dwProcessID)
+	{
+		int nIndex = path.ReverseFind('\\');
+		path = path.Right(path.GetLength() - nIndex - 1);
+		dwProcessID = FindProcess(path);
+		return (dwProcessID != 0 ? TRUE : FALSE);
+
+		BOOL bFound = FALSE;
+
+		HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
+		if ( handle == NULL )
+			return FALSE;
+
+		PROCESSENTRY32 Info;
+		Info.dwSize = sizeof(PROCESSENTRY32);
+		path.MakeLower();
+		if (::Process32First(handle, &Info))
+		{
+			do{
+				CString ss = Info.szExeFile;
+				ss.MakeLower();
+				if (ss == path)
+				{
+					dwProcessID = Info.th32ProcessID;
+					bFound = TRUE;
+					break;
+				}
+			} while (::Process32Next(handle, &Info));
+		}
+
+		CloseHandle(handle);
+		return (bFound ? TRUE : FALSE);
+	}
+
+	// 根据路径名查找进程,返回进程ID;
+	DWORD FindProcess(IN CString strProName)
+	{
+		DWORD dwProcessID = 0;
+		PROCESSENTRY32 pe32 = { 0 };
+
+		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+		if (hProcessSnap == NULL)
+		{
+			return 0;
+		}
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+
+		if (Process32First(hProcessSnap, &pe32))
+		{
+			do
+			{
+				if (_tcscmp(strProName.GetString(), pe32.szExeFile) == 0)
+				{
+					dwProcessID = pe32.th32ProcessID;
+					break;
+				}
+			} while (Process32Next(hProcessSnap, &pe32));
+		}
+		CloseHandle(hProcessSnap);
+
+		return dwProcessID;
+	}
+
+	DWORD FindProcessCount(IN LPCTSTR lpExeName)
+	{
+		DWORD dwCount = 0;
+		if ( lpExeName && lpExeName[0] != _T('\0'))
+		{
+			PROCESSENTRY32 pe32 = { 0 };
+			HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+			if (hProcessSnap == NULL) return 0;
+
+			pe32.dwSize = sizeof(PROCESSENTRY32);
+			if ( !Process32First(hProcessSnap, &pe32) )
+				return 0;
+
+			do
+			{
+				if (_tcscmp(lpExeName, pe32.szExeFile) == 0)
+					dwCount++;
+			} while (Process32Next(hProcessSnap, &pe32));
+
+			CloseHandle(hProcessSnap);
+		}
+		
+		return dwCount;
+	}
+
+	// 根据路径名查找进程,查找成功并结束;
+	int FindAndCloseProcess(IN CString strProName)
+	{
+		int nIndex = strProName.ReverseFind('\\');
+		if (nIndex != -1)	// 如果传的是全路径;
+			strProName = strProName.Right(strProName.GetLength() - nIndex - 1);
+
+		DWORD dwProcessID = 0;
+		PROCESSENTRY32 pe32 = { 0 };
+
+		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+		if (hProcessSnap == NULL)
+		{
+			return 0;
+		}
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+
+		if (Process32First(hProcessSnap, &pe32))
+		{
+			do
+			{
+				if (_tcscmp(strProName.GetBuffer(), pe32.szExeFile) == 0)
+				{
+					dwProcessID = pe32.th32ProcessID;
+					break;
+				}
+			} while (Process32Next(hProcessSnap, &pe32));
+		}
+		CloseHandle(hProcessSnap);
+
+		if (dwProcessID == 0)
+			return 0;
+
+		HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessID);
+		if (hProcess == NULL)
+			return 0;
+
+		DWORD dwError;
+		if (!TerminateProcess(hProcess, 0))
+		{
+			dwError = GetLastError();
+			CloseHandle(hProcess);
+			return -1;
+		}
+
+		// 等待进程结束响应;
+		if (WAIT_OBJECT_0 != WaitForSingleObject(hProcess, INFINITE))
+		{
+			CloseHandle(hProcess);
+			AfxMessageBox(_T("结束进程失败"));
+			return -1;
+		}
+
+		CloseHandle(hProcess);
+
+		return 1;
+	}
+
+	/************************************************************************/
+	/*
+	函数:GetDiskSpaceInfo
+	描述:获取指定目录或盘符的容量信息;
+	参数:
+	IN:	lpRootPathName 根目录名称;
+	INOUT: dTotalNum  总容量;
+	INOUT: dFreeNum 可用容量;
+	返回:
+	注意:
+	GetDiskFreeSpace函数不能满足当前超过2T的硬盘容量,因为里面的数据类型是UINT,最大支持32位(4G);
+	GetDiskFreeSpaceEx支持64位(16384P=1024*16384T)
+	能获取本机硬盘信息,但路径必须包含":"冒号, 同时还可以获取网络路径的共享硬盘大小;
+	调用约定:
+	*/
+	/************************************************************************/
+	BOOL GetDiskSpaceInfo(IN LPCTSTR lpRootPathName, IN OUT double &dTotalNum, IN OUT double &dFreeNum)
+	{
+#if 1
+		// 校验参数有效性;
+		if (lpRootPathName == NULL || _tcscmp(lpRootPathName, _T("")) == 0)
+		{
+			//_tprintf_s(_T("根目录为空!"));
+			return FALSE;
+		}
+
+		// 如果长度==1;
+		int nlen = _tcslen(lpRootPathName);
+		if ((1 == nlen) || (2 == nlen && lpRootPathName[nlen - 1] != _T(':')))
+		{
+			//_tprintf_s(_T("根目录无效!\n"));
+			return FALSE;
+		}
+
+		if (!PathFileExists(lpRootPathName))
+		{
+			//_tprintf_s(_T("根目录不存在!\n"));
+			return FALSE;
+		}
+#else
+		// 使用IsValipath判断网络路径时较慢;
+		if (!IsValidpath(lpRootPathName) || !PathFileExists(lpRootPathName)) return FALSE;
+#endif
+
+		BOOL fResult = FALSE;
+		DWORD dwSectPerClust;	// 每簇的扇区数;
+		DWORD dwBytesPerSect;	// 每个扇区的字节数;
+		DWORD dwFreeClusters;	// 可用簇数;
+		DWORD dwTotalClusters;	// 总簇数;
+
+		typedef BOOL(WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
+		P_GDFSE pGetDiskFreeSpaceEx = NULL;
+
+		/*unsigned*/ __int64 i64FreeBytesToCaller;
+		/*unsigned*/ __int64 i64TotalBytes;
+		/*unsigned*/ __int64 i64FreeBytes;
+
+		// 调用GetDiskFreeSpaceEx失败则调用GetDiskSpace;
+#ifdef UNICODE
+		pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "GetDiskFreeSpaceExW");
+#else
+		pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
+#endif
+
+		if (pGetDiskFreeSpaceEx)
+		{
+			fResult = pGetDiskFreeSpaceEx(lpRootPathName,
+				(PULARGE_INTEGER)&i64FreeBytesToCaller,
+				(PULARGE_INTEGER)&i64TotalBytes,
+				(PULARGE_INTEGER)&i64FreeBytes);
+
+			if (fResult)
+			{
+				// 将单位由byte转为G byte;
+				dTotalNum = (double)i64TotalBytes / 1024 / 1024 / 1024;
+				dFreeNum = (double)i64FreeBytes / 1024 / 1024 / 1024;
+			}
+		}
+		else
+		{
+			fResult = GetDiskFreeSpace(lpRootPathName,
+				&dwSectPerClust,
+				&dwBytesPerSect,
+				&dwFreeClusters,
+				&dwTotalClusters);
+
+			if (fResult)
+			{
+				// 成功获得容量信息;
+				i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust * dwBytesPerSect;
+				i64FreeBytes = (__int64)dwFreeClusters * dwSectPerClust * dwBytesPerSect;
+
+				// 将单位由byte转为G byte;
+				dTotalNum = (double)i64TotalBytes / 1024 / 1024 / 1024;
+				dFreeNum = (double)i64FreeBytes / 1024 / 1024 / 1024;
+			}
+		}
+
+		return fResult;
+	}
+
+
+	/************************************************************************/
+	/* 
+	函数:GetFileVersion
+	描述:获取可执行文件的文件版号;
+	参数:
+	hModule[IN]		可执行文件模块句柄;
+	dwArray[OUT]	返回的文件版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+	当hModule为空时,表示要获取的可执行文件为本程序的文件版本号;
+	*/
+	/************************************************************************/
+	BOOL GetFileVersion( IN HMODULE hModule, OUT DWORD (&dwArray)[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, dwHandle, nSize, pBuffer))
+				{
+					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+					{
+						dwArray[0] = HIWORD(pVi->dwFileVersionMS);
+						dwArray[1] = LOWORD(pVi->dwFileVersionMS);
+						dwArray[2] = HIWORD(pVi->dwFileVersionLS);
+						dwArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+						delete[]pBuffer;
+						return TRUE;
+					}
+				}
+
+				if ( pBuffer )
+					delete[]pBuffer;
+			}
+		}
+
+		return FALSE;
+	}
+
+	/************************************************************************/
+	/* 
+	函数:GetFileVersion
+	描述:获取可执行文件的文件版号;
+	参数:
+	lpFileName[IN]	可执行文件名全路径;
+	dwArray[OUT]	返回的文件版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+	*/
+	/************************************************************************/
+	BOOL GetFileVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] )
+	{
+		if ( lpFileName == NULL || !PathFileExists(lpFileName) )
+		{
+			OutputDebugString(_T("文件名错误或文件不存在\n"));
+			return FALSE;
+		}
+
+		DWORD dwHandle = 0;
+		VS_FIXEDFILEINFO *pVi = NULL;
+		INT nSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
+		if ( nSize > 0 )
+		{
+			BYTE *pBuffer = new BYTE[nSize];
+			memset(pBuffer, 0, nSize);
+
+			if ( GetFileVersionInfo(lpFileName, dwHandle, nSize, pBuffer) )
+			{
+				if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+				{
+					dwArray[0] = HIWORD(pVi->dwFileVersionMS);
+					dwArray[1] = LOWORD(pVi->dwFileVersionMS);
+					dwArray[2] = HIWORD(pVi->dwFileVersionLS);
+					dwArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+					if (pBuffer)
+						delete[]pBuffer;
+					return TRUE;
+				}
+			}
+
+			if (pBuffer)
+				delete[]pBuffer;
+		}
+
+		return FALSE;
+	}
+
+	/************************************************************************/
+	/* 
+	函数:GetProductVersion
+	描述:获取可执行文件的产品版号;
+	参数:
+	hModule[IN]		可执行文件模块句柄;
+	dwArray[OUT]	返回的产品版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+	当hModule为空时,表示要获取的可执行文件为本程序的产品版本号;
+	*/
+	/************************************************************************/
+	BOOL GetProductVersion(IN HMODULE hModule, IN DWORD (&dwArray)[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, dwHandle, nSize, pBuffer))
+				{
+					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+					{
+						dwArray[0] = HIWORD(pVi->dwProductVersionMS);
+						dwArray[1] = LOWORD(pVi->dwProductVersionMS);
+						dwArray[2] = HIWORD(pVi->dwProductVersionLS);
+						dwArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+						if(pBuffer)
+							delete[]pBuffer;
+						return TRUE;
+					}
+				}
+				if(pBuffer)
+					delete[]pBuffer;
+			}
+		}
+
+		return FALSE;
+	}
+
+	/************************************************************************/
+	/* 
+	函数:GetProductVersion
+	描述:获取可执行文件的产品版号;
+	参数:
+	lpFileName[IN]	可执行文件名全路径;
+	dwArray[OUT]	返回的产品版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+	*/
+	/************************************************************************/
+	BOOL GetProductVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] )
+	{
+		if ( lpFileName == NULL || !PathFileExists(lpFileName) )
+		{
+			OutputDebugString(_T("文件名错误或文件不存在\n"));
+			return FALSE;
+		}
+
+		DWORD dwHandle = 0;
+		VS_FIXEDFILEINFO *pVi = NULL;
+		INT nSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
+		if ( nSize > 0 )
+		{
+			BYTE *pBuffer = new BYTE[nSize];
+			memset(pBuffer, 0, nSize);
+
+			if ( GetFileVersionInfo(lpFileName, dwHandle, nSize, pBuffer) )
+			{
+				if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+				{
+					dwArray[0] = HIWORD(pVi->dwProductVersionMS);
+					dwArray[1] = LOWORD(pVi->dwProductVersionMS);
+					dwArray[2] = HIWORD(pVi->dwProductVersionLS);
+					dwArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+					if (pBuffer)
+						delete[]pBuffer;
+					return TRUE;
+				}
+			}
+
+			if (pBuffer)
+				delete[]pBuffer;
+		}
+
+		return FALSE;
+	}
+
+	/************************************************************************/
+	/* 
+		函数:
+		描述:
+		参数:
+		返回:
+		注意:
+	*/
+	/************************************************************************/
+	BOOL GetDirLastWriteTime(IN LPCTSTR lpDirName, OUT LPTSTR lpszString, IN CONST DWORD& dwSize)
+	{
+		if ( lpDirName == NULL || !PathFileExists(lpDirName))
+		{
+			OutputDebugString(_T("文件夹不存在\n"));
+			return FALSE;
+		}
+
+		// 打开文件夹;
+		HANDLE hDir = CreateFile(
+			lpDirName, 
+			GENERIC_READ,
+			FILE_SHARE_READ|FILE_SHARE_DELETE,
+			NULL, OPEN_EXISTING,
+			FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+		if ( hDir == INVALID_HANDLE_VALUE )
+		{
+			OutputDebugString(_T("打开文件夹失败\n"));
+			return FALSE;
+		}
+
+		if ( !GetLastWriteTime(hDir, lpszString, dwSize) )
+		{
+			OutputDebugString(_T("获取文件修改时间失败\n"));
+			return FALSE;
+		}
+		
+		// 关闭文件句柄;
+		CloseHandle(hDir);
+
+		return TRUE;
+	}
+
+	BOOL GetLastWriteTime(IN HANDLE hFile, OUT LPTSTR lpszString, IN CONST DWORD& dwSize)
+	{
+		// 创建时间、访问时间、修改时间;
+		FILETIME ftCreate, ftAccess, ftWrite;
+		// UTC时间、系统时间;
+		SYSTEMTIME stUTC, stLocal;
+		// 返回的结果;
+		DWORD dwRet = 0;
+
+		// Retrieve the file times for the file.
+		if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
+			return FALSE;
+
+		// Convert the last-write time to local time.
+		FileTimeToSystemTime(&ftWrite, &stUTC);
+		SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
+
+		// Build a string showing the date and time.
+		dwRet = StringCchPrintf(lpszString, dwSize, 
+			TEXT("%02d/%02d/%d  %02d:%02d"),
+			stLocal.wMonth, stLocal.wDay, stLocal.wYear,
+			stLocal.wHour, stLocal.wMinute);
+
+		return (S_OK == dwRet ? TRUE : FALSE);
+	}
+
+	BOOL SetFileLastWirteTime(IN LPCTSTR lpDirName, IN SYSTEMTIME &st)
+	{
+		if ( lpDirName == NULL || !PathFileExists(lpDirName))
+		{
+			OutputDebugString(_T("文件夹不存在\n"));
+			return FALSE;
+		}
+
+		// 打开文件夹;
+		HANDLE hDir = CreateFile(
+			lpDirName, 
+			GENERIC_WRITE,
+			FILE_SHARE_READ|FILE_SHARE_DELETE,
+			NULL, OPEN_EXISTING,
+			FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+		if ( hDir == INVALID_HANDLE_VALUE )
+		{
+			OutputDebugString(_T("打开文件夹失败\n"));
+			return FALSE;
+		}
+
+		FILETIME ft;
+		BOOL f;
+		SystemTimeToFileTime(&st, &ft);  // converts to file time format
+		// sets last-write time for file
+		f = SetFileTime(hDir, (LPFILETIME) NULL, (LPFILETIME) NULL, &ft);
+		CloseHandle(hDir);
+
+		return f;
+	}
+
+	void DeleteDirectory(CString strDir)
+	{
+		if ( strDir.IsEmpty() || !PathFileExists(strDir) )
+		{
+			OutputDebugString(_T("DeleteDirectory:路径无效!"));
+			return;
+		}
+
+		try
+		{
+			// 首先删除文件及子文件夹;   
+			CFileFind   ff;
+			BOOL   bFound = ff.FindFile(strDir + _T("\\*"), 0);
+			while (bFound)
+			{
+				bFound = ff.FindNextFile();
+				if (ff.GetFileName() == _T(".") || ff.GetFileName() == _T(".."))
+					continue;
+				// 去掉文件(夹)只读等属性;   
+				if ( SetFileAttributes(ff.GetFilePath(), FILE_ATTRIBUTE_NORMAL) )
+				{
+					if (ff.IsDirectory())
+					{   // 递归删除子文件夹;   
+						DeleteDirectory(ff.GetFilePath());
+						RemoveDirectory(ff.GetFilePath());
+					}
+					else
+					{
+						DeleteFile(ff.GetFilePath());   // Jeff:删除某文件夹下的所有子文件;
+						OutputDebugString(ff.GetFilePath());
+					}
+				}
+				else
+				{
+					DWORD dwError = GetLastError();
+					CString strError = _T("");
+					strError.Format(_T("设置文件[%s]属性失败:%d"), ff.GetFilePath(), dwError);
+				}
+			}
+			ff.Close();
+			// 然后删除该文件夹;   
+			RemoveDirectory(strDir);
+		}
+		catch (...)
+		{
+			OutputDebugString(_T("出错在函数deldir中"));
+		}
+	}
+
+	void GetHostName()
+	{
+		WSADATA WSAData = { 0 };
+		if(0 != WSAStartup(MAKEWORD(2, 2), &WSAData))
+		{
+			AfxMessageBox(_T("网络环境初始化失败!"));
+			return;
+		}
+
+		CHAR szHostName[MAX_PATH] = {0};
+		gethostname(szHostName,MAX_PATH);
+
+#ifdef UNICODE
+		INT wSize = MultiByteToWideChar(CP_ACP, 0, szHostName, -1, NULL, 0);
+		if (wSize == 0) return ;
+
+		WCHAR *pHostName = new WCHAR[wSize];
+		int convresult = MultiByteToWideChar(CP_ACP, 0, szHostName, -1, pHostName, wSize);
+		if (convresult != wSize)
+		{
+			if (pHostName) delete []pHostName;
+			return;
+		}
+#else
+		TCHAR *pHostName = szHostName;
+#endif
+		StringCchPrintf(g_szHostName, MAX_PATH, _T("%s"), pHostName);
+#ifdef UNICODE
+		delete []pHostName;
+#endif
+	}
+
+	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(LOGTYPE logType, const TCHAR* format, ...)
+	{
+		AutoThreadSection aSection(&g_csTextLog);
+		// 获取今年年份;
+		__time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		struct tm gmtm = { 0 };
+		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+#ifndef RTEST
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = { 0 };
+		if ( logType == SAT_EXE ) {
+			_stprintf_s(szlogpath, _T("%s%s\\Exector-%04d-%02d.txt"), g_szCurModuleDir, "log", gmtm.tm_year + 1900, gmtm.tm_mon + 1);
+		}
+		else if ( logType == SAT_DEV ) {
+			_stprintf_s(szlogpath, _T("%s%s\\Device-%04d-%02d.txt"), g_szCurModuleDir, "log", gmtm.tm_year + 1900, gmtm.tm_mon + 1);
+		}
+		else if ( logType == SAT_PYE ) {
+			_stprintf_s(szlogpath, _T("%s%s\\PyExecutor-%04d-%02d.txt"), g_szCurModuleDir, "log", gmtm.tm_year + 1900, gmtm.tm_mon + 1);
+		}
+		else if ( logType == SAT_TCP ) {
+			_stprintf_s(szlogpath, _T("%s%s\\TCP-%04d-%02d.txt"), g_szCurModuleDir, "log", gmtm.tm_year + 1900, gmtm.tm_mon + 1);
+		} else {
+			_stprintf_s(szlogpath, _T("%s%s\\%s-%04d-%02d.txt"), g_szCurModuleDir, "log", g_szFna, gmtm.tm_year + 1900, gmtm.tm_mon + 1);
+		}
+
+		if ( !PathFileExists(szlogpath) )
+			MKDIR(szlogpath);
+
+		// 打开或创建文件;
+		FILE* fp = NULL;
+		if (_taccess(szlogpath, 0) != -1)
+		{// 存在;
+			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"));//设定中文;
+#endif
+		// 格式化日志内容;
+		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);
+		// 将日志内容输入到文件中;
+#ifndef RTEST
+		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1900, 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);//还原区域设定;
+#else
+		printf(_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);
+#endif
+	}
+
+	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, _T("%s"), msg);
+		// 关闭文件,释放资源并设置回原语言区域;
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale); //还原区域设定;
+	}
+
+	std::string GetLocalAddress(int nType/*= MIB_IF_TYPE_ETHERNET*/)
+	{
+		int nCardNo = 1;
+		// PIP_ADAPTER_INFO结构体指针存储本机网卡信息 
+		PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
+		// 得到结构体大小,用于GetAdaptersInfo参数 
+		unsigned long stSize = sizeof(IP_ADAPTER_INFO);
+		// 调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量 
+		int nRel = GetAdaptersInfo(pIpAdapterInfo,&stSize);
+		// 记录网卡数量 
+		int netCardNum = 0;
+		// 记录每张网卡上的IP地址数量 
+		int IPnumPerNetCard = 0;
+		if(ERROR_BUFFER_OVERFLOW == nRel)
+		{
+			// 如果函数返回的是ERROR_BUFFER_OVERFLOW 
+			// 则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小 
+			// 这也是说明为什么stSize既是一个输入量也是一个输出量 
+			// 释放原来的内存空间 
+			delete pIpAdapterInfo; 
+			// 重新申请内存空间用来存储所有网卡信息 
+			pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
+			// 再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量 
+			nRel = GetAdaptersInfo(pIpAdapterInfo,&stSize);
+		}
+
+		if(ERROR_SUCCESS == nRel)
+		{
+			// 输出网卡信息 
+			// 可能有多网卡,因此通过循环去判断 
+			while (pIpAdapterInfo)
+			{
+				// 可能网卡有多IP,因此通过循环去判断 
+				IP_ADDR_STRING*pIpAddrString = &(pIpAdapterInfo->IpAddressList);
+				if ( pIpAdapterInfo->Type == nType )
+				{
+					g_strIPAddress = pIpAddrString->IpAddress.String;
+					break;
+				}
+#if 0
+				switch(pIpAdapterInfo->Type)
+				{
+				case MIB_IF_TYPE_OTHER:
+				case MIB_IF_TYPE_ETHERNET:
+				case MIB_IF_TYPE_TOKENRING:
+				case MIB_IF_TYPE_FDDI:
+				case MIB_IF_TYPE_PPP:
+				case MIB_IF_TYPE_LOOPBACK:
+				case MIB_IF_TYPE_SLIP:
+					{
+						strAddress = pIpAddrString->IpAddress.String;
+						// 需要注意的是有时可能获取的IP地址是0.0.0.0,这时需要过滤掉 
+						if(std::string("0.0.0.0") == strAddress)
+							break;
+						std::cout<<_T("第")<<nCardNo<<_T("张网卡的IP地址是")<<strAddress<<std::endl;
+						nCardNo++;
+						break;
+					}
+				default:
+					// 未知类型网卡就跳出 
+					break;
+				}
+#endif
+				pIpAdapterInfo = pIpAdapterInfo->Next;
+			}
+		}
+		// 释放内存空间 
+		if (pIpAdapterInfo)
+		{
+			delete pIpAdapterInfo;
+		}
+
+		WriteTextLog(SAT_NOR, "【当前主机IP地址:%s】", g_strIPAddress.c_str());
+
+		return g_strIPAddress;
+	}
+
+	INT GetMacAddress()
+	{
+		HDEVINFO hDevInfo;
+		DWORD MemberIndex, RequiredSize;
+		SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+		PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
+		INT nTotal = 0;
+		INT nNICKind = 0;
+
+		// 获取设备信息集;
+		hDevInfo = SetupDiGetClassDevs(&MacClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
+		if (hDevInfo == INVALID_HANDLE_VALUE)
+		{
+			return -1;
+		}
+
+		g_vtMac.clear();
+		// 枚举设备信息集中所有设备;
+		DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+		for (MemberIndex = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &MacClassGuid, MemberIndex, &DeviceInterfaceData); MemberIndex++)
+		{
+			// 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER;
+			SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL);
+
+			// 申请接收缓冲区;
+			DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
+			if ( DeviceInterfaceDetailData == NULL)
+				continue;
+			DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+			// 获取设备细节信息;
+			if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL))
+			{
+				HANDLE hDeviceFile;
+				BOOL isOK = FALSE;
+				if (_tcsnicmp(DeviceInterfaceDetailData->DevicePath + 4, TEXT("pci"), 3) != 0)
+				{
+					free(DeviceInterfaceDetailData);
+					DeviceInterfaceDetailData = NULL;
+					continue;
+				}
+				MacAddress tagMacAddress;
+				tagMacAddress.nNICKind = NIC_PCI;
+				_stprintf_s(tagMacAddress.szNICKind, _T("%s"), _T("NIC_PCI"));
+
+				// 获取设备句柄;
+				hDeviceFile = CreateFile(DeviceInterfaceDetailData->DevicePath,
+					0,
+					FILE_SHARE_READ | FILE_SHARE_WRITE,
+					NULL,
+					OPEN_EXISTING,
+					0,
+					NULL);
+
+				if (hDeviceFile != INVALID_HANDLE_VALUE)
+				{
+					ULONG dwID;
+					BYTE ucData[8];
+					DWORD dwByteRet;
+
+					// 获取原生MAC地址;
+					dwID = OID_802_3_PERMANENT_ADDRESS;
+					isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
+					if (isOK)
+					{
+						++nTotal;
+						_stprintf_s(tagMacAddress.szDevicePath, _T("%s"), DeviceInterfaceDetailData->DevicePath);
+						memset(tagMacAddress.szMacAddress, 0, sizeof(TCHAR) * MAX_PATH);
+						// 将字节数组转换成16进制字符串;
+						for (DWORD i = 0; i < dwByteRet; i++)
+						{
+							_stprintf_s(&tagMacAddress.szMacAddress[i * 3], MAX_PATH - (i * 3), (i != dwByteRet - 1) ? _T("%02X-") : _T("%02X"), ucData[i]);
+						}
+
+						g_vtMac.push_back(tagMacAddress);
+					}
+					CloseHandle(hDeviceFile);
+				}
+			}
+
+			free(DeviceInterfaceDetailData);
+			DeviceInterfaceDetailData = NULL;
+		}
+
+		SetupDiDestroyDeviceInfoList(hDevInfo);
+
+#if 1
+		g_strMacs.clear();
+		std::vector<MacAddress>::iterator it = g_vtMac.begin();
+		for (; it != g_vtMac.end(); it++)
+		{
+			g_strMacs.append(it->szMacAddress);
+			break;
+		}
+
+		WriteTextLog(SAT_NOR, "【当前主机MAC地址:%s】", g_strMacs.c_str());
+#endif
+
+		return nTotal;
+	}
+
+	std::string Replace(std::string strSrc, std::string strNew, std::string strOld)
+	{
+		while(true) {     
+			std::string::size_type pos(0);     
+			if(( pos = strSrc.find(strOld)) != std::string::npos )     
+				strSrc.replace(pos,strOld.length(),strNew);     
+			else
+				break;     
+		} 
+		return strSrc; 
+	}
+
+	BOOL Python27Dir()
+	{
+		BOOL bIsWow64 = FALSE;
+		std::string strPython27Reg = "SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath";
+		IsWow64Process(GetCurrentProcess(), &bIsWow64);
+		if ( bIsWow64 ){
+			strPython27Reg = "SOFTWARE\\WOW6432Node\\Python\\PythonCore\\2.7\\InstallPath";
+		}
+
+		HKEY hKey;
+		int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, strPython27Reg.c_str(), 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);
+
+		// 给尾加杠;
+		if ( g_szPython27Dir[_tcslen(g_szPython27Dir) - 1] != '\\')
+			_tcscat_s(g_szPython27Dir, MAX_PATH, "\\");
+
+		return TRUE;
+	}
+
+	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);
+	}
+
+};

+ 225 - 0
SerialWatch/SerialWatch/Global.h

@@ -0,0 +1,225 @@
+///************************************************************************/
+/*  Copyright (C), 2010-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __HOME_GLOBAL__
+#define __HOME_GLOBAL__
+
+#pragma once
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+namespace GLOBAL
+{
+	enum LOGTYPE{
+		SAT_NOR = 0,
+		SAT_EXE,
+		SAT_DEV,
+		SAT_PYE,
+		SAT_TCP,
+	};
+
+	typedef struct __ST_SAT_CFG__ 
+	{
+		// usb设备adb重连时长(超过该时长,执行adb kill)
+		DWORD dwAdbKillTime;
+		// adb超时断线时长;
+		DWORD dwAdbTimeout;
+		// 脚本路径;
+		TCHAR szScriptDir[MAX_PATH];
+		// Apk接口地址;
+		TCHAR szApkServer[MAX_PATH];
+		TCHAR szApkSysCode[MAX_PATH];
+		// 用例接口地址;
+		TCHAR szCaseServer[MAX_PATH];
+		TCHAR szCaseSysCode[MAX_PATH];
+		// 任务接口地址;
+		TCHAR szTaskServer[MAX_PATH];
+		TCHAR szTaskSysCode[MAX_PATH];
+		// 结果接口地址;
+		TCHAR szResultServer[MAX_PATH];
+		TCHAR szResultExcelDir[MAX_PATH];
+		// 执行器接口地址;
+		TCHAR szExecuteServer[MAX_PATH];
+		TCHAR szExecuteSysCode[MAX_PATH];
+		// TCP服务端接口;
+		DWORD dwTCPSvrPort;
+		// 脚本超时值设置;
+		DWORD dwScriptTimeout;
+		// xml目录;
+		TCHAR szCaseResultDir[MAX_PATH];
+		// 电视机串口号;
+		TCHAR szTVPort[MAX_PATH];
+		// 是否开启串口监控;
+		BOOL  bWatchTVPort;
+		// 重启关键字;
+		TCHAR szTVReboot[MAX_PATH];
+		// 关机关键字;
+		TCHAR szTVShutdown[MAX_PATH];
+		// 这个可以忽略不要;
+		typedef struct  __ST_LD__
+		{
+			TCHAR szDevice[MAX_PATH];
+			TCHAR szManu[MAX_PATH];
+			TCHAR szHardwareVersion[MAX_PATH];
+			TCHAR szModel[MAX_PATH];
+		}STLinuxDevice, *pSTLinuxDevice;
+		STLinuxDevice stLinuxDevice;
+	}STSATConfig, *pSTSATConfig;
+
+	typedef struct __PY_NOTICE__{
+		// 是否有通知(实时性,需要时段判断)
+		bool notify;
+		// 监控类型;
+		std::string report_type;
+		// 发生时间(如正常关机的通知时间);
+		std::string report_data;
+		// 接收到脚本通知的时间;
+		__int64 datetime;
+	}PyNotice, *pPyNotice;
+
+	// 只需要一个记录即可,无需记录多个;
+	extern PyNotice g_PyNotify;
+	// 全局配置文件;
+	extern STSATConfig g_stSATConfig;
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	//////////////////////////////////////////////////////////////////////////
+	extern TCHAR g_szIniFile[MAX_PATH];
+	extern TCHAR g_szHostName[MAX_PATH];			// 主机计算机名;
+	extern TCHAR g_szConnectString[MAX_PATH];		// DB连接串;
+
+	// 服务器信息;
+	extern TCHAR g_szDBSource[MAX_PATH];			// 数据库源(服务所在IP或计算机名);
+	extern TCHAR g_szDBSourcePort[MAX_PATH];		// 数据库源端口;
+	extern DWORD g_dwDBServerPort;					// 数据库源端口;
+	extern TCHAR g_szDBAccount[MAX_PATH];			// 数据库登录用户;
+	extern TCHAR g_szDBPassWord[MAX_PATH];			// 数据库登录密码;
+	extern TCHAR g_szDBName[MAX_PATH];				// 数据库名称;	
+
+	extern TCHAR g_szCurModuleFileName[MAX_PATH];
+	extern TCHAR g_szCurModuleDir[MAX_PATH];
+	extern TCHAR g_szCurModulePath[MAX_PATH];
+	extern TCHAR g_szFna[_MAX_FNAME];
+	extern TCHAR g_szExt[_MAX_EXT];
+	extern TCHAR g_szPython27Dir[MAX_PATH];
+	extern TCHAR g_szPython27ResourceConfig[MAX_PATH];
+	extern std::string g_strIPAddress;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 网卡类型;
+	enum NICKIND {
+		// pci网卡;
+		NIC_PCI,
+		// usb网卡;
+		NIC_USB,
+		// 虚拟网卡;
+		NIC_ROOT,
+		// 仿真网卡;
+		NIC_SWD,
+		// 未知类型;
+		NIC_UNK
+	};
+
+	typedef struct __MAC_ADDRESS__
+	{
+		INT nNICKind;
+		TCHAR szNICKind[16];
+		TCHAR szMacAddress[MAX_PATH];
+		TCHAR szDevicePath[MAX_PATH];
+	} MacAddress, * pMacAddress;
+
+	extern std::string g_strMacs;
+	extern std::vector<MacAddress> g_vtMac;
+	//////////////////////////////////////////////////////////////////////////
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	// 判断公历是否有效;
+	extern BOOL IsValidDate(IN LPCTSTR lpDate);
+	// 判断农历是否有效;
+	extern BOOL IsValidLunanrDate(IN LPCTSTR lpDate);
+	// 获取配置文件函数;
+	extern int GetIniInfo(IN const TCHAR *szPath = NULL, const TCHAR *szIniName = NULL);
+
+	// 获取网卡地址;
+	INT GetMacAddress();
+	//////////////////////////////////////////////////////////////////////////
+	// 字符串系列全局函数;
+	extern BOOL CompareNoCase(IN TString& str1, IN TString& str2);
+	extern BOOL IsStringExist(IN CString& str, IN CStringArray &tagAry);
+	extern BOOL IsStringExist(IN TString& str, IN vector<TString> &tagVt);
+	extern BOOL IsStringExistNoCase(IN CString& str, IN CStringArray &tagAry);
+	extern BOOL IsStringExistNoCase(IN CONST TString& str, IN CStringArray &tagAry);
+	extern BOOL IsStringExistNoCase(IN CONST TString& str, IN vector<TString> &tagVt);
+	extern TString lowercase(IN const TString &Str);
+	extern TString uppercase(IN const TString &Str);
+	extern int match(IN CONST TString &sExt, IN CONST TString &sFile);
+	extern TString getfilename(IN CONST TString &file);
+	extern CString getfilename(IN CONST CString &file);
+
+	//////////////////////////////////////////////////////////////////////////
+	// 进程相关函数;
+	extern BOOL FindAppProcessID(IN CString path, OUT DWORD &dwProcessID);
+	extern DWORD FindProcess(IN CString strProName);
+	extern DWORD FindProcessCount(IN LPCTSTR lpExeName);
+	extern int FindAndCloseProcess(IN CString strProName);
+
+	// 文件函数;
+	extern  BOOL GetDiskSpaceInfo(IN LPCTSTR lpRootPathName,IN OUT double &dTotalNum, IN OUT double &dFreeNum);
+
+	extern BOOL GetFileVersion( IN HMODULE hModule, IN DWORD (&dwArray)[4]);
+	extern BOOL GetFileVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] );
+	extern BOOL GetProductVersion( IN HMODULE hModule, IN DWORD (&dwArray)[4]);
+	extern BOOL GetProductVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] );
+
+	// 获取文件夹的修改时间;
+	extern BOOL GetDirLastWriteTime(IN LPCTSTR lpDirName, OUT LPTSTR lpszString, IN CONST DWORD& dwSize);
+	// 设置文件夹的修改时间;
+	extern BOOL SetDirLastWriteTime();
+	// 获取指定文件句柄的修改时间;
+	extern BOOL GetLastWriteTime(IN HANDLE hFile, OUT LPTSTR lpszString, IN CONST DWORD& dwSize);
+	// 设置指定文件夹的修改时间;
+	extern BOOL SetFileLastWirteTime(IN LPCTSTR lpDirName, IN SYSTEMTIME &st);
+	// 删除指定的目录所有文件;
+	extern void DeleteDirectory(CString strDir);
+	//
+	extern void GetHostName();
+	// 创建目录;
+	bool MKDIR(LPCTSTR dir);
+	void WriteTextLog(LOGTYPE logType, const TCHAR* format, ...);
+	// 写脚本日志;
+	void WritePythonLog(LPCTSTR file, const TCHAR* msg);
+	// 获取本机IP地址;
+	std::string GetLocalAddress(int nType = MIB_IF_TYPE_ETHERNET);
+	// 替换指定字符串;
+	std::string Replace(std::string strSrc, std::string strNew, std::string strOld);
+	// 获取Python27路径;
+	BOOL Python27Dir();
+	// 指定字符串分隔;
+	void Split(std::string str1, std::string str2, std::vector<std::string> &vt);
+};
+
+#endif

+ 48 - 0
SerialWatch/SerialWatch/ReadMe.txt

@@ -0,0 +1,48 @@
+========================================================================
+    动态链接库:SerialWatch 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 SerialWatch DLL。
+
+本文件概要介绍组成 SerialWatch 应用程序的
+的每个文件的内容。
+
+
+SerialWatch.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+SerialWatch.cpp
+    这是主 DLL 源文件。
+
+	此 DLL 在创建时不导出任何符号。因此,在生成此 DLL 时
+	将不会产生 .lib 文件。如果希望此项目
+	成为其他某个项目的项目依赖项,则需要
+	添加代码以从 DLL 导出某些符号,
+	以便产生一个导出库,或者,也可以在项目“属性页”对话框中的
+	“链接器”文件夹中,将“常规”属性页上的
+	“忽略输入库”属性设置为“是”。
+
+/////////////////////////////////////////////////////////////////////////////
+应用程序向导创建了下列资源:
+
+SerialWatch.rc
+这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
+此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 SerialWatch.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 17 - 0
SerialWatch/SerialWatch/Resource.h

@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by SerialWatch.rc
+//
+
+#define IDS_APP_TITLE			103
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE	101
+#define _APS_NEXT_COMMAND_VALUE		40001
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#endif
+#endif

+ 159 - 0
SerialWatch/SerialWatch/SerialWatch.cpp

@@ -0,0 +1,159 @@
+// SerialWatch.cpp : 定义 DLL 应用程序的导出函数。
+//
+
+#include "stdafx.h"
+#include "SerialWatch.h"
+#include "SynSerial.h"
+
+CSynSerial g_TVPort;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 唯一的应用程序对象
+
+CWinApp theApp;
+
+using namespace std;
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
+
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+		// TODO: 在此处为应用程序的行为编写代码。
+		if ( OpenTVPort(9, 115200, 8, NOPARITY, 1) ) {
+#ifdef _DEBUG
+			printf("打开串口成功\n");
+#endif
+			// 开始监听;
+			StartMonitor();
+
+			//RTK_USBUpgrade(9, 0x1B); // ESC键升级;
+			RTK_USBUpgrade(9, 0x09); // TAB键升级;
+
+			Sleep(30000);
+			CloseTVPort();
+		}
+	}
+
+	system("pause");
+
+	return nRetCode;
+}
+
+SERIALWATCH_API BOOL OpenTVPort(int nPort, DWORD dwBaudrate, BYTE ByteSize, BYTE Parity, BYTE StopBits)
+{
+	// 关闭打开的;
+	if ( g_TVPort.IsOpen() )
+		g_TVPort.CloseSerialPort();
+
+	g_TVPort.OpenSerialPort(nPort, dwBaudrate, ByteSize, Parity, StopBits, 0, 1000);
+
+	return g_TVPort.IsOpen();
+}
+
+SERIALWATCH_API BOOL IsOpen()
+{
+	return g_TVPort.IsOpen();
+}
+
+SERIALWATCH_API void StartMonitor()
+{
+	if ( g_TVPort.IsOpen() )
+		g_TVPort.StartThread();
+}
+
+SERIALWATCH_API void SendCommand(LPCTSTR lpCommand, int nSendCount, int nSleep)
+{
+	if ( !g_TVPort.IsOpen() || !lpCommand)
+		return ;
+
+	bool bRet;
+	for ( int i = 0; i < nSendCount; i++ ) {
+		bRet = g_TVPort.WriteComm((BYTE*)lpCommand, _tcslen((TCHAR*)lpCommand));
+#ifdef _DEBUG
+		printf(_T("写串口:%s\n"), bRet ? _T("成功") : _T("失败"));
+#endif
+		Sleep(nSleep);
+	}
+}
+
+// 关闭串口;
+SERIALWATCH_API void CloseTVPort()
+{
+	g_TVPort.EndofThread();
+	if ( g_TVPort.IsOpen() ) {
+		g_TVPort.CloseSerialPort();
+	}
+}
+
+SERIALWATCH_API bool WatchWord(LPCTSTR lpWatchWord, int nWatchTime)
+{
+	// 设置要监听的单词,由线程去判断;
+	if ( lpWatchWord == NULL )
+		return false;
+
+	return g_TVPort.FindWord(lpWatchWord);
+}
+
+SERIALWATCH_API void ClearBuffer()
+{
+	g_TVPort.ClearBuffer();
+}
+
+SERIALWATCH_API bool RTK_USBUpgrade(INT nPort, BYTE byKey)
+{
+	bool bRet = false;
+	if ( IsOpen() ) {
+		// 回车;
+		SendCommand(_T("\r"), 5, 500);
+		// 判断是否出现console字样;
+		if ( WatchWord(_T("console:/")) ) {
+#ifdef _DEBUG
+			printf("找到关键字\n");
+#endif
+			// 重启;
+			SendCommand(_T("reboot\r"), 1);	
+			if ( WatchWord(_T("Terminated"), 100) ) {
+				ClearBuffer();
+				while ( TRUE ) {
+					// 连续发送150次按键;
+					SendCommand((LPCTSTR)&byKey, 150);
+					if ( byKey == 0x1B ){ // ESC键;
+						if ( WatchWord(_T("Realtek>"), 150) ) {
+#ifdef _DEBUG
+							printf("找到关键字\n");
+#endif
+							SendCommand(_T("\r"), 2, 100);
+							SendCommand(_T("go r\r"), 1, 1000);
+							bRet = true;
+							break;
+						}
+					} else if (byKey == 0x09) { // TAB键;
+						if ( WatchWord(_T("loader start!"), 150) ) {
+#ifdef _DEBUG
+							printf("找到关键字\n");
+#endif
+							bRet = true;
+							break;
+						}
+					}
+				}
+			}				
+		}
+	}
+
+	return bRet;
+}
+

+ 29 - 0
SerialWatch/SerialWatch/SerialWatch.h

@@ -0,0 +1,29 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SERIALWATCH_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// SERIALWATCH_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+#ifdef SERIALWATCH_EXPORTS
+#define SERIALWATCH_API __declspec(dllexport)
+#else
+#define SERIALWATCH_API __declspec(dllimport)
+#endif
+
+
+// 打开串口;
+SERIALWATCH_API BOOL OpenTVPort(int nPort, DWORD dwBaudrate = 115200, BYTE ByteSize = 8, BYTE Parity = NOPARITY, BYTE StopBits = 1);
+// 串口是否打开;
+SERIALWATCH_API BOOL IsOpen();
+// 关闭串口;
+SERIALWATCH_API void CloseTVPort();
+// 开启监听;
+SERIALWATCH_API void StartMonitor();
+// 发送指令;//命令、发送次数、每次间隔多少毫秒;
+SERIALWATCH_API void SendCommand(LPCTSTR lpCommand, int nSendCount = 1, int nSleep = 0);
+// 清空Buffer;//在监听关键字前清空;
+SERIALWATCH_API void ClearBuffer();
+// 监听指定关键字是否出现;
+SERIALWATCH_API bool WatchWord(LPCTSTR lpWatchWord, int nWatchTime = 3000);
+// RTK的升级方案;
+SERIALWATCH_API bool RTK_USBUpgrade(INT nPort, BYTE byKey);

+ 69 - 0
SerialWatch/SerialWatch/SerialWatch.rc

@@ -0,0 +1,69 @@
+//Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#include "afxres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+   IDS_APP_TITLE       "SerialWatch"
+END
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED

+ 259 - 0
SerialWatch/SerialWatch/SerialWatch.vcproj

@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="SerialWatch"
+	ProjectGUID="{4319EFC1-51BB-4000-933B-6EA7BBEA3B97}"
+	RootNamespace="SerialWatch"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SERIALWATCH_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SERIALWATCH_EXPORTS"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			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=".\SerialWatch.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\SynSerial.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			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=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\SerialWatch.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\SynSerial.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\SerialWatch.rc"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 426 - 0
SerialWatch/SerialWatch/SynSerial.cpp

@@ -0,0 +1,426 @@
+#include "StdAfx.h"
+#include "SynSerial.h"
+
+ThreadSection CSynSerial::s_csClearBuffer;
+CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
+, m_dwInQueue(1024)
+, m_dwOutQueue(1024)
+{
+	memset(&m_dcb, 0, sizeof(DCB));
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
+
+	m_hEvent = NULL;
+	m_hThread = NULL;
+
+	// 初始化重叠对象;
+	ZeroMemory(&m_writeOverlapped,sizeof(m_writeOverlapped));
+	if (m_writeOverlapped.hEvent != NULL) {
+		ResetEvent(m_writeOverlapped.hEvent);
+		m_writeOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+	}
+
+	ZeroMemory(&m_readOverlapped,sizeof(m_readOverlapped));
+	if (m_readOverlapped.hEvent != NULL) {
+		ResetEvent(m_readOverlapped.hEvent);
+		m_readOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+	}
+}
+
+CSynSerial::~CSynSerial(void)
+{
+	EndofThread();
+	CloseSerialPort();
+}
+
+BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwBaudRate, IN CONST BYTE & bySize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST INT & nInterval)
+{
+	ASSERT(byCommPort);
+	CloseSerialPort();
+
+	_stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult) {
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = bySize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult) {
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult) {
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 5000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult) {
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CSynSerial::ReOpenSerialPort()
+{
+	ASSERT(_tcslen(m_szSerialPort));
+	CloseSerialPort();
+
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		CloseHandle(m_hSerialPort);
+		m_hSerialPort = INVALID_HANDLE_VALUE;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void CSynSerial::CloseSerialPort()
+{
+	if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
+		CloseHandle(m_hSerialPort);
+	m_hSerialPort = INVALID_HANDLE_VALUE;
+}
+
+BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byByteSize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST DWORD & dwInQueue, IN CONST DWORD & dwOutQueue)
+{
+	if (!IsOpen())
+		return FALSE;
+
+	BOOL bResult = FALSE;
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = byByteSize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 3000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
+{
+}
+
+void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
+{
+}
+
+bool CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
+{
+	if (!IsOpen())
+		return false;
+
+	if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
+	{
+		return false;
+	}
+	
+	DWORD dwErrorFlags;
+	DWORD dwBytesWritten = 0;	// 实际写入的字节数;
+	// 写前, 清除错误;
+	COMSTAT ComStat;
+	ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);	
+	// 写前,清空缓存区;
+	PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, &m_writeOverlapped) ) {
+		DWORD dwError = GetLastError();
+		if ( ERROR_IO_PENDING == GetLastError() ) {
+			while(!GetOverlappedResult(m_hSerialPort, &m_writeOverlapped, &dwBytesWritten, FALSE)){
+#ifdef _DEBUG
+				printf("\t\t写串口出错: %d,%d,%d,%d,%d,%d\n", 
+					GetLastError(), m_writeOverlapped.Internal, m_writeOverlapped.InternalHigh,
+					m_writeOverlapped.Offset, m_writeOverlapped.OffsetHigh,dwBytesWritten);
+#endif
+			}
+		}
+	}	
+
+#ifdef _DEBUG
+	if (dwBytesWritten == nWriteSize)
+		printf("\t写串口成功:%s\n", pWirteBuf);
+	else
+		printf("\t写串口失败:%s\n",pWirteBuf);
+#endif
+
+	// 返回写入字节数;
+	return (dwBytesWritten == nWriteSize);
+}
+
+DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
+{
+	if (!IsOpen())
+		return 0;
+
+	if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
+	{
+		return 0;
+	}
+
+	DWORD dwError = 0;
+	DWORD dwRealRead = 0;
+	if ( !ClearCommError(m_hSerialPort, &dwError, NULL) ) {
+		PurgeComm(m_hSerialPort, PURGE_TXABORT|PURGE_TXCLEAR);
+	}
+ 
+	int i = 0;
+	TCHAR szLog[MAX_PATH] ;
+	if ( !ReadFile(m_hSerialPort, pReadBuf, dwReadSize, &dwRealRead, &m_readOverlapped) ) {
+		if ( STATUS_PENDING == m_readOverlapped.Internal ) {
+			while(!GetOverlappedResult(m_hSerialPort, &m_readOverlapped, &dwRealRead, FALSE)){
+
+#ifdef _DEBUG
+				Sleep(20);
+				_stprintf_s(szLog,"\t\t读串口出错: %d = %d,%d,%d,%d,%d,%d\n", ++i,
+					GetLastError(), m_readOverlapped.Internal, m_readOverlapped.InternalHigh,
+					m_readOverlapped.Offset, m_readOverlapped.OffsetHigh, dwRealRead);
+				OutputDebugString(szLog);
+#endif
+
+				// 是否仍在等待;
+				if ( STATUS_PENDING != m_readOverlapped.Internal ) {
+					break;
+				}
+				
+				// 线程是否结束;
+				if ( m_hThread && WaitForSingleObject(m_hEvent, 0) == WAIT_OBJECT_0  )
+					break;
+			}
+		}
+	}
+	
+	return m_readOverlapped.InternalHigh;
+}
+
+void CSynSerial::StartThread()
+{
+	if ( m_hEvent || m_hThread )
+		return;
+
+	m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if ( m_hEvent == NULL )
+		return;
+
+	m_hThread = CreateThread(NULL, 0, ThreadWatch, this, 0, NULL);
+	if ( m_hThread == NULL ) {
+		SetEvent(m_hEvent);
+		CloseHandle(m_hEvent);
+		m_hEvent = NULL;
+	}
+}
+
+void CSynSerial::EndofThread()
+{
+	// 设置有信号;
+	if ( m_hEvent ) {
+		SetEvent(m_hEvent);
+	}
+	// 等待线程结束;
+	if ( m_hThread ) {
+		WaitForSingleObject(m_hThread, INFINITE);
+		CloseHandle(m_hThread);
+		m_hThread = NULL;
+	}
+
+	if ( m_hEvent )
+		CloseHandle(m_hEvent);
+	m_hEvent = NULL;
+}
+
+
+DWORD CSynSerial::ThreadWatch(LPVOID lpVoid)
+{
+	DWORD dwRealRead;
+	TCHAR szValue[1024] = {0};
+	CSynSerial *pthat = (CSynSerial*)lpVoid;
+	
+	do 
+	{
+		if ( (dwRealRead = pthat->ReadComm((BYTE*)szValue, 1024)) > 0) {
+			AutoThreadSection aSection(&s_csClearBuffer);
+			pthat->m_strbuffer.append(szValue, dwRealRead);
+#ifdef _DEBUG
+			printf(_T("buffer=%s\n"), pthat->m_strbuffer.c_str());
+#endif
+		}
+
+	} while ( WaitForSingleObject(pthat->m_hEvent, 50) == WAIT_TIMEOUT );
+
+#ifdef _DEBUG
+	printf("线程结束\n");
+#endif
+
+	return 0;
+}
+
+bool CSynSerial::FindWord(std::string strWord, int nWatchTime )
+{
+	bool found = false;
+	int nSize = nWatchTime/50;
+	for ( int i = 0; i < nSize; i++ ) {
+		if ( m_strbuffer.find(strWord) != std::string::npos ) {
+			found = true;
+			break;
+		}
+		Sleep(10);
+	}
+
+	return found;
+}

+ 99 - 0
SerialWatch/SerialWatch/SynSerial.h

@@ -0,0 +1,99 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Home], 保留所有权利;
+/*  模 块 名:同步串口模块;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Home];
+/*  日    期:[12/20/2017];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Home];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __SYN_SERIAL__
+#define __SYN_SERIAL__
+
+#include "CritSection.h"
+
+#pragma once
+
+#define MAX_PORT_LEN 10
+
+class CSynSerial
+{
+public:
+	CSynSerial(void);
+	virtual ~CSynSerial(void);
+
+private:
+	DCB		m_dcb;
+	HANDLE	m_hSerialPort;
+	COMMTIMEOUTS	m_cts;
+	OVERLAPPED		m_writeOverlapped;
+	OVERLAPPED		m_readOverlapped;
+	// 串口号(1~255);
+	TCHAR	m_szSerialPort[MAX_PORT_LEN];
+	// 输入缓存大小(byte);
+	DWORD	m_dwInQueue;
+	// 输出缓存大小(byte);
+	DWORD	m_dwOutQueue;
+	std::string m_strbuffer;
+	static ThreadSection s_csClearBuffer;
+public:
+	inline BOOL IsOpen() const {
+		return (m_hSerialPort == NULL || m_hSerialPort == INVALID_HANDLE_VALUE) ? FALSE : TRUE;
+	}
+
+	// 打开串口;
+	BOOL OpenSerialPort(
+		IN CONST BYTE& byCommPort,		// 串口号;
+		IN CONST DWORD& dwBaudRate,		// 波特率;
+		IN CONST BYTE& bySize,			// 数据位;
+		IN CONST BYTE& byParity,		// 校验位;
+		IN CONST BYTE& byStopBits,		// 停止位;
+		IN CONST BYTE& byStartAddr,		// 起始地址;
+		IN CONST INT& nInterval			// 间隔时间;
+	);
+	// 重装打开串口;
+	BOOL ReOpenSerialPort();
+	// 关闭串口;
+	void CloseSerialPort();
+	// 设置串口参数;
+	BOOL SetSerialPort(
+		IN CONST DWORD& dwBaudRate,		// 波特率;
+		IN CONST BYTE& byByteSize,		// 数据位;
+		IN CONST BYTE& byParity,		// 校验位;
+		IN CONST BYTE& byStopBits,		// 停止位;
+		IN CONST BYTE& byStartAddr,		// 起始地址;
+		IN CONST DWORD& dwInQueue,		// 输入缓存;
+		IN CONST DWORD& dwOutQueue		// 输出缓存;
+		);
+
+	// 设置dcb参数;
+	void SetSerialDCB(IN CONST DCB &dcb);
+	// 设置commtimeouts参数;
+	void SetSerialCommTimeouts(IN CONST COMMTIMEOUTS &commTimeouts);
+
+	virtual bool WriteComm(IN BYTE *pWirteBuf, IN CONST INT32 nWriteSize);
+	virtual DWORD ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout = 300);
+
+public:
+	HANDLE  m_hEvent;
+	HANDLE	m_hThread;
+	void StartThread();
+	void EndofThread();
+	static DWORD WINAPI ThreadWatch(LPVOID lpVoid);
+	bool FindWord(std::string strWord, int nWatchTime = 3000);
+	void ClearBuffer() {
+		AutoThreadSection aSection(&s_csClearBuffer);
+		m_strbuffer.clear();
+	};
+};
+
+#endif // __SYN_SERIAL__

+ 8 - 0
SerialWatch/SerialWatch/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// SerialWatch.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 33 - 0
SerialWatch/SerialWatch/stdafx.h

@@ -0,0 +1,33 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include <afx.h>
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+// Windows 头文件:
+#include <windows.h>
+
+
+
+// TODO: 在此处引用程序需要的其他头文件

+ 24 - 0
SerialWatch/SerialWatch/targetver.h

@@ -0,0 +1,24 @@
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif