scbc.sat2 5 роки тому
батько
коміт
1a6568828b

+ 981 - 0
SATService/SATService/Global.cpp

@@ -0,0 +1,981 @@
+#pragma once
+
+#include "stdafx.h"
+#include "Global.h"
+
+#include <tlhelp32.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+#include <WinVer.h>		
+#pragma comment(lib,"version.lib")
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	TCHAR g_szIniFile[MAX_PATH] = {0};
+	TCHAR g_szHostName[MAX_PATH] = {0};			// 主机计算机名;
+	TCHAR g_szModulePath[MAX_PATH];				// 软件目录;
+	TCHAR g_szModuleFileName[MAX_PATH];			// 软件名称;
+	TCHAR g_szConnectString[MAX_PATH];			// DB连接串;
+	TCHAR g_szBranchId[MAX_PATH];				// 本店加密锁域名;
+
+	// 服务器信息;
+	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];					// 数据库名称;	
+
+	CHAR g_szKeyPath[MAX_PATH];					// 加密狗USB位置;
+
+	//////////////////////////////////////////////////////////////////////////
+	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 )
+	{
+		TCHAR szDrive[_MAX_DRIVE] = { 0 };
+		TCHAR szDir[_MAX_DIR] = { 0 };
+		TCHAR szFna[_MAX_DIR] = { 0 };
+		TCHAR szExt[_MAX_DIR] = { 0 };
+		DWORD dwRet = ::GetModuleFileName(NULL, g_szModuleFileName, sizeof(g_szModuleFileName) / sizeof(TCHAR));
+
+		_tsplitpath_s(g_szModuleFileName, szDrive, szDir, szFna, szExt);
+		StringCchCat(g_szModulePath, MAX_PATH, szDrive);
+		StringCchCat(g_szModulePath, 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("%sServiceInfo.ini"), g_szModulePath);
+
+		HANDLE hFile = CreateFile(szIniPath, 0/*GENERIC_READ*/, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+		if (ERROR_FILE_NOT_FOUND == GetLastError())
+		{
+			return -1;
+		}
+
+		// 获取服务器端信息;
+		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbSource"), _T(""), g_szDBSource, MAX_PATH, szIniPath);
+		g_dwDBServerPort = GetPrivateProfileInt(_T("DatabaseInfo"), _T("dbServerPort"), 0, szIniPath);
+		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbAccount"), _T(""), g_szDBAccount, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbPassWord"), _T(""), g_szDBPassWord, MAX_PATH, szIniPath);
+		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbName"), _T(""), g_szDBName, MAX_PATH, szIniPath);
+
+		//g_dwCSPort = GetPrivateProfileInt(_T("NetWorkInfo"), _T("TCPChatPort"), 5678, szIniPath);
+
+		if (g_dwDBServerPort != 0)
+			StringCchPrintf(g_szConnectString, MAX_PATH, _T("driver={SQL Server};Server=%s,%d;database=%s;uid=%s;pwd=%s"),
+			g_szDBSource, g_dwDBServerPort, g_szDBName, g_szDBAccount, g_szDBPassWord);
+		else
+			StringCchPrintf(g_szConnectString, MAX_PATH, _T("driver={SQL Server};Server=%s;database=%s;uid=%s;pwd=%s"),
+			g_szDBSource, g_szDBName, g_szDBAccount, g_szDBPassWord);
+
+		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
+	}
+
+};

+ 109 - 0
SATService/SATService/Global.h

@@ -0,0 +1,109 @@
+///************************************************************************/
+/*  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
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	//////////////////////////////////////////////////////////////////////////
+	extern TCHAR g_szIniFile[MAX_PATH];
+	extern TCHAR g_szHostName[MAX_PATH];			// 主机计算机名;
+	extern TCHAR g_szModulePath[MAX_PATH];			// 软件目录;
+	extern TCHAR g_szModuleFileName[MAX_PATH];		// 软件名称;
+	extern TCHAR g_szConnectString[MAX_PATH];		// DB连接串;
+	extern TCHAR g_szBranchId[MAX_PATH];			// 分店域名;
+
+	// 服务器信息;
+	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 CHAR g_szKeyPath[MAX_PATH];				// 加密狗USB位置;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	// 判断公历是否有效;
+	extern BOOL IsValidDate(IN LPCTSTR lpDate);
+	// 判断农历是否有效;
+	extern BOOL IsValidLunanrDate(IN LPCTSTR lpDate);
+	// 获取配置文件函数;
+	extern int GetIniInfo(IN const TCHAR *szPath = NULL, const TCHAR *szIniName = NULL);
+
+	//////////////////////////////////////////////////////////////////////////
+	// 字符串系列全局函数;
+	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();
+
+};
+
+#endif

+ 56 - 0
SATService/SATService/MTVERIFY.H

@@ -0,0 +1,56 @@
+/*
+ * MtVerify.h
+ *
+ * Error handling for applications in
+ * "Multitheading Applications in Win32"
+ *
+ * The function PrintError() is marked as __inline so that it can be
+ * included from one or more C or C++ files without multiple definition
+ * errors. For the examples in this book, this works fine.
+ * To use the PrintError() in an application, it should be taken out,
+ * placed in its own source file, and the "__inline" declaration removed
+ * so the function will be globally available.
+ */
+#ifndef _MTVERIFY_HEADER_
+#define _MTVERIFY_HEADER_
+
+#pragma comment( lib, "USER32" )
+
+#include <strsafe.h>
+#include <crtdbg.h>
+#define MTASSERT(a) _ASSERTE(a)
+
+
+#define MTVERIFY(a) if (!(a)) PrintError(#a,__FILE__,__LINE__,GetLastError())
+
+__inline void PrintError(LPTSTR linedesc, LPTSTR filename, int lineno, DWORD errnum)
+{
+	LPTSTR lpBuffer;
+	TCHAR errbuf[MAX_PATH];
+#ifdef _WINDOWS
+	TCHAR modulename[MAX_PATH];
+#else // _WINDOWS
+	DWORD numread;
+#endif // _WINDOWS
+
+	FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		errnum,
+		LANG_NEUTRAL,
+		(LPTSTR)&lpBuffer,
+		0,
+		NULL );
+
+//	_stprintf(errbuf, _T("\nThe following call failed at line %d in %s:\n\n%s\n\nReason: %s\n"), lineno, filename, linedesc, lpBuffer);
+	StringCchPrintf(errbuf, MAX_PATH, _T("\nThe following call failed at line %d in %s:\n\n%s\n\nReason: %s\n"), lineno, filename, linedesc, lpBuffer);
+#ifndef _WINDOWS
+	WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, _tcslen(errbuf), &numread, FALSE );
+	Sleep(3000);
+#else
+	GetModuleFileName(NULL, modulename, MAX_PATH);
+	//MessageBox(NULL, errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
+#endif
+	exit(EXIT_FAILURE);
+}
+
+#endif

+ 89 - 0
SATService/SATService/MainProcess.cpp

@@ -0,0 +1,89 @@
+#include "StdAfx.h"
+#include "MainProcess.h"
+#include "WindowService.h"
+
+CMainProcess::CMainProcess(void)
+{
+	m_hBackupDatabase = NULL;
+	m_hCheckServices = NULL;
+	m_hEvent1 = NULL;
+	m_hEvent2 = NULL;
+}
+
+CMainProcess::~CMainProcess(void)
+{
+}
+
+void CMainProcess::StartWork()
+{
+	m_hEvent1 = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if ( m_hEvent1 == NULL )
+	{
+		_tprintf_s(_T("创建事件失败\n"));
+		return;
+	}
+
+	m_hEvent2 = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if ( m_hEvent2 == NULL )
+	{
+		_tprintf_s(_T("创建事件失败2\n"));
+		return;
+	}
+
+	m_hCheckServices = CreateThread(NULL, 0, CheckSvcStatusThread, this, 0, NULL);
+	if ( m_hCheckServices == NULL)
+	{
+		SetEvent(m_hEvent1);
+		SetEvent(m_hEvent2);
+		CloseHandle(m_hEvent1);
+		CloseHandle(m_hEvent2);
+		m_hEvent1 = NULL;
+		m_hEvent2 = NULL;
+		_tprintf_s(_T("创建线程失败\n"));
+		return;
+	}
+
+	m_hBackupDatabase = CreateThread(NULL, 0, BackupDatabaseThread, this, 0, NULL);
+	if ( m_hBackupDatabase == NULL )
+	{
+		SetEvent(m_hEvent1);
+		SetEvent(m_hEvent2);
+		CloseHandle(m_hEvent1);
+		CloseHandle(m_hEvent2);
+		m_hEvent1 = NULL;
+		m_hEvent2 = NULL;
+		WaitForSingleObject(m_hCheckServices,INFINITE);
+		if (m_hBackupDatabase)
+			CloseHandle(m_hBackupDatabase);
+		m_hBackupDatabase = NULL;
+		_tprintf_s(_T("创建线程失败2\n"));
+		return;
+	}
+}
+
+void CMainProcess::EndofWork()
+{
+
+}
+
+DWORD CMainProcess::CheckSvcStatusThread(LPVOID lpVoid)
+{
+	CMainProcess *that = (CMainProcess*)lpVoid;
+
+	do 
+	{
+	} while ( WaitForSingleObject(that->m_hEvent1, 200) == WAIT_TIMEOUT );
+
+	return 0;
+}
+
+DWORD CMainProcess::BackupDatabaseThread(LPVOID lpVoid)
+{
+	CMainProcess *that = (CMainProcess*)lpVoid;
+
+	do 
+	{
+	} while ( WaitForSingleObject(that->m_hEvent2, 200) == WAIT_TIMEOUT );
+
+	return 0;
+}

+ 65 - 0
SATService/SATService/MainProcess.h

@@ -0,0 +1,65 @@
+/************************************************************************/
+/*  Copyright (C), 2010-2020, [Jeff], 保留所有权利;
+/*  模 块 名:服务的主要处理类;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[5/6/2011];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __MAIN_PROCESS__
+#define __MAIN_PROCESS__
+
+#pragma once
+
+class CMainProcess
+{
+	CMainProcess(void);
+public:
+	// 单例对象模式;
+	static CMainProcess* GetInstance()
+	{
+		static CMainProcess* pInstance = NULL;
+		if ( pInstance == NULL )
+		{
+			pInstance = new CMainProcess;
+		}
+
+		return pInstance;
+	}
+
+	~CMainProcess(void);
+
+protected:
+	// 线程控制句柄;
+	HANDLE  m_hEvent1;
+	// 检查服务线程句柄;
+	HANDLE	m_hCheckServices;
+	// 线程控制句柄;
+	HANDLE  m_hEvent2;
+	// 备份数据库线程句柄;
+	HANDLE	m_hBackupDatabase;
+
+	// 其他接口;
+public:
+	// 工作开始函数;	
+	void StartWork();
+	// 工作结束函数;
+	void EndofWork();
+
+	// 检测服务在线线程;
+	static DWORD WINAPI CheckSvcStatusThread(LPVOID lpVoid);
+	static DWORD WINAPI BackupDatabaseThread(LPVOID lpVoid);
+
+};
+
+#endif

+ 9 - 8
SATService/SATService/Resource.h

@@ -2,16 +2,17 @@
 // Microsoft Visual C++ generated include file.
 // Used by SATService.rc
 //
+#define IDI_ICON1                       101
+#define IDI_MICON                       101
+#define IDS_APP_TITLE                   103
 
-#define IDS_APP_TITLE			103
-
-// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
-//
+// Next default values for new objects
+// 
 #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
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 30 - 0
SATService/SATService/RunPython.h

@@ -0,0 +1,30 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 RUNPYTHON_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// RUNPYTHON_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+#ifdef RUNPYTHON_EXPORTS
+#define RUNPYTHON_API __declspec(dllexport)
+#else
+#define RUNPYTHON_API __declspec(dllimport)
+#endif
+
+// 此类是从 RunPython.dll 导出的
+//class RUNPYTHON_API CRunPython {
+//public:
+//	CRunPython(void);
+//	// TODO: 在此添加您的方法。
+//};
+//
+//extern RUNPYTHON_API int nRunPython;
+
+// 运行脚本;
+RUNPYTHON_API DWORD RunPyScript(LPCTSTR lpScriptFile, LPCTSTR lpExtraSentence, LPCTSTR lpScriptLog, BOOL bSubProcess);
+// 结束脚本;
+RUNPYTHON_API bool StopPyScript(DWORD dwScriptId, BOOL bSubProcess);
+// 脚本是否结束;
+RUNPYTHON_API bool IsPyScriptOver(DWORD dwScriptId, BOOL bSubProcess);
+// 清除脚本;
+RUNPYTHON_API void CleanPyScript(DWORD dwScriptId);
+

+ 377 - 0
SATService/SATService/SATHTTP.h

@@ -0,0 +1,377 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SATHTTP_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// SATHTTP_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+#ifdef SATHTTP_EXPORTS
+#define SATHTTP_API __declspec(dllexport)
+#else
+#define SATHTTP_API __declspec(dllimport)
+#endif
+
+// 此类是从 SATHTTP.dll 导出的
+class SATHTTP_API CSATHTTP 
+{
+	std::string url;
+public:
+	CSATHTTP(void);
+	// TODO: 在此添加您的方法。
+};
+
+namespace SATParameters{
+	//////////////////////////////////////////////////////////////////////////
+	// 通用的结构体;
+	typedef struct __ST_DEVICE__{
+		std::string strStatus;				// 0表示设备空闲; 1表示设备忙碌
+		std::string strDeviceSerial;
+		std::string strHardwareVersion;
+		std::string strManu;
+		std::string strDeviceMac;
+		std::string strLastJobStartTime;
+		std::string strLastTimeBreak;
+		std::string strComments;
+		std::string strCPU;
+		std::string strSoftwareVersion;
+		std::string strPhoneNumber;
+		std::string strLastJobFinishTime;
+		std::string strMemory;
+		std::string strModel;
+		std::string strLastJob;
+		std::string strLastTimeConnected;
+		std::string strElectric;
+	}STDevice, *pSTDevice;
+
+	typedef struct __ST_RESPONE__
+	{
+		std::string strCode;
+		std::string strMessage;
+		std::string strStr;
+	}STRespone, *pSTRespone;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 1、登录SAT的请求参数;
+	typedef struct __ST_LOGIN_REQ__{
+		std::string strUserName;
+		std::string strStatus;			// 0:表示请求登录; 1:表示请求登出;
+		std::string strDeleteStatus;
+		std::string strIP;
+		std::string strMemory;
+		std::string strStorage;
+		std::string strConnectTime;
+		std::string strExecuteName;
+		std::string strMAC;
+		std::string strDisconnectTime;
+		std::string strPassword;
+		std::string strCPU;
+	}STLoginReq, *pSTLoginReq;
+
+	// 登录SAT返回结果;
+	typedef struct __ST_LOGIN_RESP__:__ST_RESPONE__{
+		int	nPortCount;
+		int	nCompanyId;
+		std::string strRunnerToken;
+	}STLoginResp, *pSTLoginResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 2、更新设备信息的请求参数;
+	typedef struct __ST_UPDATE_DEVICE_REQ__
+	{
+		std::string strStatus;				// 0:表示空闲; 1:离线; 2:表示忙碌; 3=?; 4:任务异常?; 5=忙碌中?;
+		std::string strUserName;
+		std::string strIP;
+		std::string strStorage;
+		std::string strRunnerName;
+		std::string strMAC;
+		std::string strReportType;
+		std::string strStartTime;
+		std::string strMemory;
+		std::string strEndTime;
+		std::string strCPU;
+		std::vector<STDevice> devicelist;
+	}STUpdateDeviceReq, *pSTUpdateDeviceReq;
+
+	typedef struct __ST_UPDATE_DEVICE_RESP__:__ST_RESPONE__
+	{
+		
+	}STUpdateDeviceResp, *pSTUpdateDeviceResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 3、SAT心跳请求参数;
+	typedef struct __ST_HEARTBEAT_REQ__{
+		std::string strUserName;
+		std::string strRunnerMac;
+		std::vector<STDevice> devicelist;
+	}STHeartbeatReq, *pSTHeartbeatReq;
+
+	typedef struct __ST_CASE__
+	{
+		std::string strIndex;
+		std::string strCaseName;
+		std::string strMainFilePath;
+		std::string strId;
+		std::string strCaseType;
+	}STCase, *pSTCase;
+
+	typedef struct __ST_JOB__
+	{
+		std::string strCloudPort;
+		std::string strExecuteIP;
+		std::string strMonkeyPctSysKeys;
+		std::string strRedRatDeviceName;
+		std::string strExecuteId;
+		// std::vector<std::string> vtRunSceneParams;
+		std::string strMonkeyPctAppSwitch;
+		std::string strDeviceId;
+		std::string strLoopNumber;
+		std::vector<std::string> vtEmails;
+		std::string strTaskType;	// 1=表示SAT任务可执行, 2=表示SAT上停止了任务,请在执行完当前脚本后退出; 3=表示SAT上停止任务,并要求马上停止;
+		std::string strMonkeyFrequency;
+		std::string strCloudVersion;
+		std::string strTaskInstanceName;
+		std::string strRepeatRunTime;
+		std::string strMonkeyTime;
+		std::string strOutEquipmentId;
+		std::string strPoweroff;
+		std::string strFilePath;
+		std::string strScriptFailRepeart;
+		std::string strTaskInstanceId;
+		std::string strUserId;
+		std::string strDiffTaskInstanceFlag;
+		std::string strBusCode;
+		std::string strRound;
+		std::string strControlType;
+		std::string strMonkeyPctMajornav;
+		std::string strTaskName;
+		std::string strMonkeyType;
+		std::string strMonkeyDictate;
+		std::string strDetectedDeviceName;
+		std::string strExecuteName;
+		std::string strProjectName;
+		std::string strProjectId;
+		std::string strUniqueId;
+		std::string strTaskId;
+		std::string strSoftwareVersion;
+		std::string strMonkeyPctNav;
+		std::vector<STCase> vtCases;
+	}STJob, *pSTJob;
+
+	typedef struct __ST_TASK__
+	{
+		std::string strInstanceName;
+		std::string strExecutionStatus;
+		std::string strInstanceType;
+		int nExecuteId;
+		std::string strRequestIP;
+		std::string strTaskUseType;
+		int nDeviceId;
+		std::vector<std::string> vtEmails;
+		std::string strDiffTaskInstanceFlag;
+		std::string strTaskType;
+		int nInstanceId;
+		std::string strProgress;
+		std::string strStartTime;
+		std::string strStopTime;
+		std::string strTaskName;
+		int Id;			// 注意:对应__ST_NOTIFY_JOB_START_REQ__的strInstanceId,而非__ST_TASK__.nInstanceId;
+		int fd;
+		int nTaskId;
+		STJob Job;
+	}STTask, *pSTTask;
+
+	// SAT心跳返回结果;
+	typedef struct __ST_HEARTBEAT_RESP__:__ST_RESPONE__{
+		std::vector<STTask> vtTask;
+	}STHeartbeatResp, *pSTHeartbeatResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 4、通知SAT任务开始;
+	typedef struct __ST_NOTIFY_JOB_START_REQ__
+	{
+		std::string strInstanceId;
+		std::string strSignalImageUrl;
+		std::string strDeviceId;
+		std::string strTaskId;
+		std::string strExecuteId;
+	}STNotifyJobStartReq, *pSTNotifyJobStartReq;
+
+	typedef struct __ST_NOTIFY_JOB_START_RESP__:__ST_RESPONE__
+	{
+		
+	}STNotifyJobStartResp, *pSTNotifyJobStartResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 5、SetResultList;
+	typedef struct __ST_JOB_PROCESS_REQ__
+	{
+		std::string strResultState;		// 空表示Runner开始执行任务; 1=表示Runner已执行完成任务;
+		std::string strCaseScene;
+		std::string strCaseStep;
+		std::string strApkMD5;
+		std::string strCrashTime;
+		std::string strRunnerId;
+		std::string strCPUInfo;
+		std::string strRunnedActionNameList;
+		std::string strArtificialResult;
+		std::string strArtificialModify;
+		std::string strRunnerName;
+		std::string strTaskType;
+		std::string strCaseRepeat;
+		std::string strApplicationGroup;
+		std::string strInstanceId;
+		std::string strCaseId;
+		std::string strProgress;
+		std::string strReusltMessage;
+		std::string strJobRepeat;
+		std::string strScreenShot;
+		std::string strStartTime;
+		std::string strCrashNumber;
+		std::string strCaseName;
+		std::string strFailedReason;
+		std::string strImgName;
+		std::string strCaseIndex;
+		std::string strDeviceId;
+		std::string strSceneIndex;
+		std::string strTaskId;
+		std::string strAnalysis;
+		std::string strDevnceName;
+		std::string strInfoType;
+		std::string strMemoryInfo;
+		std::string strEndTime;
+		std::string strRoundNumber;
+		std::string strResultType;
+		std::string strOperationStep;
+	}STJobProcessReq, *pSTJobProcessReq;
+
+	typedef struct __ST_JOB_PROCESS_RESP__:__ST_RESPONE__
+	{
+		std::string strIsDelete;
+	}STJobProcessResp, *pSTJobProcessResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 6、获取脚本下载地址;
+	typedef struct __ST_SCRIPURL_RESP__
+	{
+		std::string strCaseType;
+		std::string strCode;
+		std::string strURL;
+		std::string strMessage;
+		std::string strProjectId;	
+		// 脚本保存路径;
+		std::string strScripFile;
+	}STScriptUrlResp,*pSTScriptUrlResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 7、保存用例脚本或任务日志;
+	typedef struct __ST_STOP_TASK_RESP__:__ST_RESPONE__
+	{
+		std::string strData;
+	}STStopTaskResp, *pSTStopTaskResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 8、保存用例脚本或任务日志;
+	typedef struct __ST_SAVE_LOG_REQ__
+	{
+		std::string strUserId;
+		std::string strFileType;
+		std::string strCaseId;
+		std::string strTaskId;
+		std::string strExecuteId;
+		std::string strUploads;		// 要上传的文件;
+	}STSaveLogReq, *pSTSaveLogReq;
+
+	typedef struct __ST_SAVE_LOG_RESP__:__ST_RESPONE__
+	{
+		std::string strData;
+	}STSaveLogResp, *pSTSaveLogResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 8、保存用例脚本或任务日志;
+	typedef struct __ST_SAVE_FILE_REQ__
+	{
+		std::string strRoundNum;
+		std::string strCaseRepeat;
+		std::string strJobRepeat;
+		std::string strInstanceId;
+		std::string strDeviceId;
+		std::string strExecuteId;
+		std::string strTaskName;
+		std::string strSceneIndex;
+		std::string strTaskId;
+		std::string strCaseId;
+		std::string strDeviceName;
+		std::string strRunnerName;
+		std::string strRunnerIP;
+		std::string strRunnerMAC;
+		std::string strCaseName;
+		std::string strCaseIndex;
+		std::string strTaskRepeat;
+		std::string strBusCode;
+		std::string strFileType;
+		std::string strCaseStep;
+		// 要上传的文件;
+		std::string strUploads;
+	}STSaveFileReq, *pSTSaveFileReq;
+
+	typedef struct __ST_SAVE_FILE_RESP__:__ST_RESPONE__
+	{
+		std::string strData;
+	}STSaveFileResp, *pSTSaveFileResp;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 9、保存用例图片;
+	typedef struct __ST_SAVE_IMG_REQ__
+	{
+		std::string strInstanceId;
+		std::string strDeviceId;
+		std::string strRoundNum;
+		std::string strCaseId;
+		std::string strCaseStep;
+		std::string strTaskType;
+		std::string strExecuteId;
+		std::string strCaseRepeat;
+		std::string strJobRepeat;
+		// 要上传的文件;
+		std::string strUploads;
+	}STSaveImgReq, *pSTSaveImgReq;
+
+	typedef struct __ST_SAVE_IMG_RESP__:__ST_RESPONE__
+	{
+		std::string strData;
+	}STSaveImgResp, *pSTSaveImgResp;
+}
+
+extern SATHTTP_API int nSATHTTP;
+
+// 登录接口;
+SATHTTP_API	int Login(std::string url, const SATParameters::STLoginReq &stLoginReq, SATParameters::STLoginResp &stLoginResp) throw();
+
+// 登录完后,必须向服务器更新设备信息,否则SAT上执行任务时无法更新Runner出来;
+SATHTTP_API int UpdateDeviceMessage(std::string url, const SATParameters::STUpdateDeviceReq &stUpdateDeviceReq, SATParameters::STUpdateDeviceResp &stUpdateDeviceResp) throw();
+
+// 更新完设备信息后,向服务器查询任务;
+SATHTTP_API int Heartbeat(std::string url, const SATParameters::STHeartbeatReq &stHeartbeatReq, SATParameters::STHeartbeatResp &stHeartbeatResp) throw();
+
+// 从心跳包中获取到任务后,通知SAT任务开始(变更SAT上的任务状态);
+// 注意坑:STNotifyJobStartReq.strInstanceId引用的是STTask.Id而非STTask.nInstanceId
+SATHTTP_API int SetResult(std::string url, const SATParameters::STNotifyJobStartReq &stNotifyJobStartReq, SATParameters::STNotifyJobStartResp &stNotifyJobStartResp) throw();
+
+// 通知SAT用例脚本已开始;
+SATHTTP_API int SetResultList(std::string url, const SATParameters::STJobProcessReq &stJobProcessReq, SATParameters::STJobProcessResp &stJobProcessResp) throw();
+
+SATHTTP_API int GetCaseFileListUrl(std::string url, std::string strCaseId, SATParameters::STScriptUrlResp &stScriptUrlResp) throw();
+SATHTTP_API int DownloadScript(std::string url, std::string strCaseId, std::string strSaveDir, SATParameters::STScriptUrlResp &stScriptUrlResp) throw();
+
+// 停止Runner上的任务;
+// 注意:strInstnaceId对应的是STTask.nInstanceId;
+SATHTTP_API int StopTaskFromRunner(std::string url, std::string strInstnaceId, SATParameters::STStopTaskResp &stStopTaskResp) throw();
+
+SATHTTP_API int SaveCaseOrTaskLog(std::string url, const SATParameters::STSaveLogReq &stSaveLogReq, SATParameters::STSaveLogResp &stSaveLogResp) throw();
+SATHTTP_API int SaveResultFile(std::string url, const SATParameters::STSaveFileReq &stSaveFileReq, SATParameters::STSaveFileResp &stSaveFileResp) throw();
+SATHTTP_API int SaveResultImg(std::string url, const SATParameters::STSaveImgReq &stSaveImgReq, SATParameters::STSaveImgResp &stSaveImgResp) throw();
+SATHTTP_API int GetIdNumber();
+SATHTTP_API int GetPyCaseInfo();
+SATHTTP_API int GetCaseInfo();
+
+
+

+ 71 - 312
SATService/SATService/SATService.cpp

@@ -3,74 +3,46 @@
 
 #include "stdafx.h"
 #include "SATService.h"
-#include <direct.h>
+#include "MainProcess.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #endif
 
-
-__if_not_exists(NotifyJobStart)
-{
-	int NotifyJobStart(std::string url, const SATParameters::STNotifyJobStartReq &stNotifyJobStartReq, SATParameters::STNotifyJobStartResp &stNotifyJobStartResp) throw()
-	{
-		return SetResult(url, stNotifyJobStartReq, stNotifyJobStartResp);
-	}
-}
-
-__if_not_exists(ProcessJob)
-{
-	int ProcessJob(std::string url, const SATParameters::STJobProcessReq &stJobProcessReq, SATParameters::STJobProcessResp &stJobProcessResp) throw()
-	{
-		return SetResultList(url, stJobProcessReq, stJobProcessResp);
-	}
-}
 // 唯一的应用程序对象
 
 CWinApp theApp;
 
 using namespace std;
 
-bool MKDIR(LPCTSTR dir) 
-{
-	//////////////////////////////////////////////////////////////////////////
-	// 创建目录;
-	int nleft = 0;
-	int nIndex = -1;
-	std::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("\\"));
+extern int test();
 
-		if (nIndex != string::npos)
-		{
-			if (_mkdir(strdir.substr(0, nIndex + nleft).c_str()) == -1 && (errno != EEXIST))
-			{
-				return false;
-			}
+// 工作启动回调函数;
+void CALLBACK WorkStart()
+{
+#ifdef _DEBUG
+	Sleep(8000);
+#endif
+	WindowsService::GetDebugPriv();
+	CMainProcess::GetInstance()->StartWork();
+}
 
-			nleft += nIndex + 1;
-		}
-	} while (nIndex != -1);
+// 工作结束回调函数;
+void CALLBACK WorkEndof()
+{
+	CMainProcess::GetInstance()->EndofWork();
+}
 
-	return true;
-};
 
 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 {
 	int nRetCode = 0;
 
+	// 直接获得前景窗口的句柄;
+	HWND hwnd = GetForegroundWindow(); 
+	SendMessage(hwnd , WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NULL,MAKEINTRESOURCE(IDI_MICON)));
+	HMODULE hModule = ::GetModuleHandle(NULL);
+
 	// 初始化 MFC 并在失败时显示错误
 	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 	{
@@ -81,284 +53,71 @@ int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 	else
 	{
 		// TODO: 在此处为应用程序的行为编写代码。
-		//std::string host = "http://10.118.158.52:8580";//"http://10.118.158.198:8090";
-		std::string host = "http://10.118.158.198:8090";
-		SATParameters::STDevice stDevice;
-		stDevice.strStatus = "0";
-		stDevice.strDeviceSerial = "192.168.1.119:5555";
-		stDevice.strHardwareVersion = "MS6488";
-		stDevice.strManu = "MStar";
-		stDevice.strDeviceMac = "";
-		stDevice.strLastJobStartTime = "";
-		stDevice.strLastTimeBreak = "";
-		stDevice.strComments = "";
-		stDevice.strCPU = "";
-		stDevice.strSoftwareVersion = "1522659174";
-		stDevice.strPhoneNumber = "";
-		stDevice.strLastJobFinishTime = "";
-		stDevice.strMemory = "";
-		stDevice.strModel = "Generic Linux on tcl_ms6488_cn_64_n";
-		stDevice.strLastJob = "";
-		stDevice.strLastTimeConnected = "2019-12-16 10:16:01";
-		stDevice.strElectric = "";
-		// ##########################先登录##############################;
-		SATParameters::STLoginReq stLoginReq;
-		SATParameters::STLoginResp stLoginResp;
-		std::string url = host + "/btc_execute_se/ajaxInteractiveManage!executeLogin.action";
-		// 示例值;
-		stLoginReq.strUserName = "superAdmin";
-		stLoginReq.strStatus = "0";
-		stLoginReq.strDeleteStatus = "";
-		stLoginReq.strIP = "10.118.158.175";
-		stLoginReq.strStorage = "";
-		stLoginReq.strConnectTime = "";
-		stLoginReq.strExecuteName = "";
-		stLoginReq.strMAC = "40:16:7e:23:10:53";
-		stLoginReq.strDisconnectTime = "";
-		stLoginReq.strPassword = "123456";
-		stLoginReq.strCPU = "";
-
-		if ( !Login(url, stLoginReq, stLoginResp) )
-		{
-			system("pause");
-			return -1;
+#ifdef _DEBUG
+		//return test();
+#endif
+		Global::GetIniInfo();
+
+		// 进程存在,直接退出;
+		TCHAR szExeName[MAX_PATH] = {0};
+		TCHAR szDrive[_MAX_DRIVE] = { 0 };
+		TCHAR szDir[_MAX_DIR] = { 0 };
+		TCHAR szFna[_MAX_DIR] = { 0 };
+		TCHAR szExt[_MAX_DIR] = { 0 };
+		_tsplitpath_s(Global::g_szModuleFileName, szDrive, szDir, szFna, szExt);
+		_stprintf_s(szExeName, _T("%s%s"), szFna, szExt);
+		if ( Global::FindProcessCount(szExeName) > 1)
+		{// 进程计数大于1,退出;
+			return 0;
 		}
 
-		printf("登录返回:code=%s, msg=%s, str=%s, portCount=%d, companyid=%d, runnertoken=%s\n",
-			stLoginResp.strCode.c_str(),
-			stLoginResp.strMessage.c_str(),
-			stLoginResp.strStr.c_str(),
-			stLoginResp.nPortCount,
-			stLoginResp.nCompanyId,
-			stLoginResp.strRunnerToken.c_str()
-			);		
+		// 设置服务名和描述;
+		_stprintf_s(WindowsService::g_szSvcName, _T("SAT Service"));
+		_stprintf_s(WindowsService::g_szlpSvrDescription, _T("SAT自动化服务"));
 
-		while(true)
+		// 1.先判断服务是否存在;
+		if ( WindowsService::IsSvcInstalled())
 		{
-			// ##########################更新设备信息##############################;
-			SATParameters::STUpdateDeviceReq stUpdateDeviceReq;
-			SATParameters::STUpdateDeviceResp stUpdateDeviceResp;
-			__if_not_exists(url)
-			{			
-				std::string url = host + "/btc_execute_se/ajaxInteractiveManage!updateDeviceMessage.action";
-			}
-			__if_exists(url)
-			{
-				url = host + "/btc_execute_se/ajaxInteractiveManage!updateDeviceMessage.action";
-			}
-
-			stUpdateDeviceReq.strStatus = "0";
-			stUpdateDeviceReq.strUserName = "superAdmin";		
-			stUpdateDeviceReq.strIP = "10.118.158.175";
-			stUpdateDeviceReq.strStorage = "228092536KB";
-			stUpdateDeviceReq.strRunnerName = "SAT-Admin";
-			stUpdateDeviceReq.strMAC = "40:16:7e:23:10:53";
-			stUpdateDeviceReq.strReportType = "1";
-			stUpdateDeviceReq.strStartTime = "2019-12-16 19:15:30";
-			stUpdateDeviceReq.strMemory = "8938544KB";
-			stUpdateDeviceReq.strEndTime = "";
-			stUpdateDeviceReq.strCPU = "24.7%";
-			stUpdateDeviceReq.devicelist.push_back(stDevice);
-
-			if ( UpdateDeviceMessage(url, stUpdateDeviceReq, stUpdateDeviceResp) )
-			{
-				printf("更新设备信息成功:code=%s, msg=%s, str=%s\n",
-					stLoginResp.strCode.c_str(),
-					stLoginResp.strMessage.c_str(),
-					stLoginResp.strStr.c_str());
-			}
-			else
+			// 卸载服务;
+			if ( argc > 1)
 			{
-				printf("更新设备信息失败!\n");
-			}
+				if (_tcscmp((TCHAR *)argv[1], _T("/uninstall")) == 0)
+					WindowsService::DoDeleteSvc(WindowsService::g_szSvcName);
+				else
+					_tprintf_s(_T("未有卸载服务参数行\n"));
 
-			// ##########################心跳包机制##############################;
-			SATParameters::STHeartbeatReq stHeartbeatReq;
-			SATParameters::STHeartbeatResp stHeartbeatResp;
-			__if_not_exists(url)
-			{			
-				std::string url = host + "/btc_execute_se/ajaxInteractiveManage!executeHeartbeat.action";
+				return 0;
 			}
-			__if_exists(url)
+			else 
 			{
-				url = host + "/btc_execute_se/ajaxInteractiveManage!executeHeartbeat.action";
-			}
-
-			// 示例值;
-			//stDevice.strStatus = "0";
-			//stDevice.strDeviceSerial = "192.168.1.119:5555";
-
-			stHeartbeatReq.strUserName = "superAdmin";
-			stHeartbeatReq.strRunnerMac = "40:16:7e:23:10:53";
-			stHeartbeatReq.devicelist.push_back(stDevice);
-			if ( Heartbeat(url, stHeartbeatReq, stHeartbeatResp) )
-			{
-				printf("登录返回:code=%s, msg=%s, str=%s\n",
-					stHeartbeatResp.strCode.c_str(),
-					stHeartbeatResp.strMessage.c_str(),
-					stHeartbeatResp.strStr.c_str());
-
-				// 判断是否有任务获取成功;
-				if ( stHeartbeatResp.vtTask.size() )
+				WindowsService::InitSvcVar();
+				WindowsService::SetCallBack(WorkStart, WorkEndof);
+				SERVICE_TABLE_ENTRY st[] =
 				{
-					// #########################################################################################
-					// 通知SAT变更任务状态;
-					SATParameters::STTask stTask = stHeartbeatResp.vtTask[0];
-					SATParameters::STNotifyJobStartReq stNotifyJobStartReq;
-					SATParameters::STNotifyJobStartResp stNotifyJobStartResp;
+					{ WindowsService::g_szSvcName, (LPSERVICE_MAIN_FUNCTION)WindowsService::ServiceMain },
+					{ NULL, NULL }
+				};
 
-					__if_not_exists(url)
-					{			
-						std::string url = host + "/btc_execute_se/ajaxInteractiveManage!setResult.action";
-					}
-					__if_exists(url)
-					{
-						url = host + "/btc_execute_se/ajaxInteractiveManage!setResult.action";
-					}
-
-					TCHAR szValue[36] = {0};
-					_itoa_s(stTask.nDeviceId, szValue, 10);
-					stNotifyJobStartReq.strDeviceId = szValue;
-
-					_itoa_s(stTask.nExecuteId, szValue, 10);
-					stNotifyJobStartReq.strExecuteId = szValue;
-
-					// _itoa_s(stTask.nInstanceId, szValue, 10); // 误导:应该使用id而不是nInstanceId
-					_itoa_s(stTask.Id, szValue, 10);
-					stNotifyJobStartReq.strInstanceId = szValue;					
-
-					_itoa_s(stTask.nTaskId, szValue, 10);
-					stNotifyJobStartReq.strTaskId = szValue;
-
-					stNotifyJobStartReq.strSignalImageUrl = "D:\\\\SAT\\\\Runner\\\\btc_runner_se\\\\runner\\\\output\\\\";//ODF_NPI_RT2841\\\\20191216101613370\\\\192.168.1.119_5555";
-					stNotifyJobStartReq.strSignalImageUrl.append(stTask.strTaskName+"\\\\");
-					stNotifyJobStartReq.strSignalImageUrl.append(stTask.Job.strUniqueId+"\\\\");
-					stNotifyJobStartReq.strSignalImageUrl.append(stTask.Job.strDeviceId);
-					
-					for( int n = 0; n < 2; n++)
-					{						
-						// 查询任务是否已在SAT上存在;
-						if ( NotifyJobStart(url, stNotifyJobStartReq, stNotifyJobStartResp) )
-						{
-							// 更新设备为忙碌状态;
-							// 忙碌状态,此时请求Heartbeat将不会查询任务;
-							stDevice.strStatus = "2";
-							printf("NotifyJobStart 成功\n");
-						}
-						else
-						{
-							printf("NotifyJobStart 失败\n");
-						}
-					}
-
-					stDevice.strStatus = "0";
-					// #########################################################################################
-					// 开始Job;
-					SATParameters::STJobProcessReq stJobProcessReq;
-					SATParameters::STJobProcessResp stJobProcessResp;
-					__if_not_exists(url)
-					{			
-						std::string url = host + "/btc_execute_se/ajaxInteractiveManage!setResultList.action";
-					}
-					__if_exists(url)
-					{
-						url = host + "/btc_execute_se/ajaxInteractiveManage!setResultList.action";
-					}
-
-					{
-						stJobProcessReq.strResultState = "1";
-						stJobProcessReq.strCaseScene = "";
-						stJobProcessReq.strCaseStep = "0";
-						stJobProcessReq.strApkMD5 = "";
-						stJobProcessReq.strCrashTime = "";
-						// 就是Task中的ExecuteId
-						_itoa_s(stTask.nExecuteId, szValue, 10);
-						stJobProcessReq.strRunnerId = szValue;
-						stJobProcessReq.strCPUInfo = "0";
-						stJobProcessReq.strRunnedActionNameList = "";
-						stJobProcessReq.strArtificialResult = "";
-						stJobProcessReq.strArtificialModify = "";
-						stJobProcessReq.strRunnerName = "";
-						stJobProcessReq.strTaskType = "FUNCTIONALITY";
-						stJobProcessReq.strCaseRepeat = "";
-						stJobProcessReq.strApplicationGroup = "";
-						// 实例Id;
-						_itoa_s(stTask.nInstanceId, szValue, 10);
-						stJobProcessReq.strInstanceId = szValue;
-						stJobProcessReq.strCaseId = "";
-						stJobProcessReq.strProgress = "0";
-						stJobProcessReq.strReusltMessage = "任务开始";
-						stJobProcessReq.strJobRepeat = "";
-						stJobProcessReq.strScreenShot = "";
-						stJobProcessReq.strStartTime = "2019-12-16 10:16:43";
-						stJobProcessReq.strCrashNumber = "";
-						stJobProcessReq.strCaseName = "";
-						stJobProcessReq.strFailedReason = "";
-						stJobProcessReq.strImgName = "";
-						stJobProcessReq.strCaseIndex = "";
-						// 实例Id;
-						_itoa_s(stTask.nDeviceId, szValue, 10);
-						stJobProcessReq.strDeviceId = szValue;
-						stJobProcessReq.strSceneIndex = "";
-						// 实例Id;
-						_itoa_s(stTask.nTaskId, szValue, 10);
-						stJobProcessReq.strTaskId = szValue;
-						stJobProcessReq.strAnalysis = "";
-						// 设备名称:即DeviceSerial;
-						stJobProcessReq.strDevnceName = stDevice.strDeviceSerial;
-						// 固定为:TOTAL
-						stJobProcessReq.strInfoType = "TOTAL";
-						// 如果是Android设备,需要通过adb获取;
-						stJobProcessReq.strMemoryInfo = stDevice.strMemory;
-						stJobProcessReq.strEndTime = "2019-12-16 10:18:20";
-						stJobProcessReq.strRoundNumber = "1";
-						stJobProcessReq.strResultType = "0";
-						stJobProcessReq.strOperationStep = "";
-					}
-
-					// 
-					if ( ProcessJob(url, stJobProcessReq, stJobProcessResp) )
-					{
-						// 开始下载脚本;
-						__if_not_exists(url)
-						{			
-							std::string url = host + "/btc_caseManagement_se/ajaxInteractiveManage!getCaseFileListUrl.action";
-						}
-						__if_exists(url)
-						{
-							url = host + "/btc_caseManagement_se/ajaxInteractiveManage!getCaseFileListUrl.action";
-						}
-
-						SATParameters::STScriptUrlResp stScriptUrlResp;
-						std::vector<SATParameters::STCase>::iterator it = stTask.Job.vtCases.begin();
-						for ( ; it != stTask.Job.vtCases.end(); it++ )
-						{
-							if ( DownloadScript(url, it->strId, "D:\\SAT\\", stScriptUrlResp) )
-							{
-								printf("获取脚本下载地址成功:%s\n路径:%s\n", stScriptUrlResp.strURL.c_str(), stScriptUrlResp.strScripFile.c_str());
-								DWORD dwScriptId = RunPyScript(stScriptUrlResp.strScripFile.c_str(), "", "D:\\SAT\\log.txt", TRUE);
-								if ( dwScriptId != -1 )
-								{
-									while( !IsPyScriptOver(dwScriptId, TRUE) )
-										Sleep(100);
-								}
-								CleanPyScript(dwScriptId);
-							}
-							else
-							{
-								printf("获取脚本下载地址失败\n");
-							}
-						}						
-					}
+				if (!::StartServiceCtrlDispatcher(st))	// 在直接双击.exe时,这步会运行失败;
+				{
+					//LOG4C((LOG_NOTICE,"服务已安装,须系统运行控制"));
+					WindowsService::SvcReportEvent(_T("Register Service Main Function Error!"));
+					return 0;
 				}
 			}
-
-			Sleep(3000);
 		}
 
-	}
+		// 2.不存在,安装服务;
+		WindowsService::InitSvcVar();
+		WindowsService::SetCallBack(WorkStart, WorkEndof);
+		SERVICE_TABLE_ENTRY st[] =
+		{
+			{ WindowsService::g_szSvcName, (LPSERVICE_MAIN_FUNCTION)WindowsService::ServiceMain },
+			{ NULL, NULL }
+		};
 
-	system("pause");
+		WindowsService::SvcInstall();
+	}
 
 	return nRetCode;
 }

+ 30 - 16
SATService/SATService/SATService.rc

@@ -1,20 +1,25 @@
-//Microsoft Visual C++ 生成的资源脚本。
+// Microsoft Visual C++ generated resource script.
 //
 #include "resource.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
 /////////////////////////////////////////////////////////////////////////////
 //
-// 从 TEXTINCLUDE 2 资源生成。
+// Generated from the TEXTINCLUDE 2 resource.
 //
 #include "afxres.h"
+
 /////////////////////////////////////////////////////////////////////////////
 #undef APSTUDIO_READONLY_SYMBOLS
 
+/////////////////////////////////////////////////////////////////////////////
+// 中文(中华人民共和国) resources
+
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
-LANGUAGE 4, 2
+#ifdef _WIN32
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
 #pragma code_page(936)
-
+#endif //_WIN32
 
 #ifdef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
@@ -22,18 +27,18 @@ LANGUAGE 4, 2
 // TEXTINCLUDE
 //
 
-1 TEXTINCLUDE
+1 TEXTINCLUDE 
 BEGIN
     "resource.h\0"
 END
 
-2 TEXTINCLUDE
+2 TEXTINCLUDE 
 BEGIN
     "#include ""afxres.h""\r\n"
     "\0"
 END
 
-3 TEXTINCLUDE
+3 TEXTINCLUDE 
 BEGIN
     "\r\n"
     "\0"
@@ -41,17 +46,27 @@ END
 
 #endif    // APSTUDIO_INVOKED
 
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MICON               ICON                    "main.ico"
+
 /////////////////////////////////////////////////////////////////////////////
 //
-// 字符串表
+// String Table
 //
 
-STRINGTABLE
+STRINGTABLE 
 BEGIN
-   IDS_APP_TITLE       "SATService"
+    IDS_APP_TITLE           "SATService"
 END
 
-#endif
+#endif    // 中文(中华人民共和国) resources
 /////////////////////////////////////////////////////////////////////////////
 
 
@@ -59,11 +74,10 @@ END
 #ifndef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
 //
-// 从 TEXTINCLUDE 3 资源生成。
+// Generated from the TEXTINCLUDE 3 resource.
 //
-#ifndef _AFXDLL
-#include "l.CHS\\afxres.rc"
-#endif
+
 
 /////////////////////////////////////////////////////////////////////////////
-#endif    // 不是 APSTUDIO_INVOKED
+#endif    // not APSTUDIO_INVOKED
+

+ 43 - 0
SATService/SATService/SATService.vcproj

@@ -63,6 +63,7 @@
 				Name="VCLinkerTool"
 				AdditionalDependencies="SATHTTP.lib RunPython.lib"
 				LinkIncremental="2"
+				UACExecutionLevel="2"
 				GenerateDebugInformation="true"
 				SubSystem="1"
 				TargetMachine="1"
@@ -135,7 +136,9 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
+				AdditionalDependencies="SATHTTP.lib RunPython.lib"
 				LinkIncremental="1"
+				UACExecutionLevel="2"
 				GenerateDebugInformation="true"
 				SubSystem="1"
 				OptimizeReferences="2"
@@ -173,6 +176,14 @@
 			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=".\MainProcess.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\SATService.cpp"
 				>
@@ -197,12 +208,32 @@
 					/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\test.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\WindowService.cpp"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Í·Îļþ"
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
+			<File
+				RelativePath=".\Global.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MainProcess.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MTVERIFY.H"
+				>
+			</File>
 			<File
 				RelativePath=".\Resource.h"
 				>
@@ -227,12 +258,24 @@
 				RelativePath=".\targetver.h"
 				>
 			</File>
+			<File
+				RelativePath=".\WindowService.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=".\icon1.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\main.ico"
+				>
+			</File>
 			<File
 				RelativePath=".\SATService.rc"
 				>

+ 1718 - 0
SATService/SATService/WindowService.cpp

@@ -0,0 +1,1718 @@
+#include "stdafx.h"
+#include "WindowService.h"
+#include <psapi.h>
+#include <tlhelp32.h>
+#pragma comment ( lib, "psapi.lib" )
+#include <Aclapi.h>
+#include <strsafe.h>
+#include <shlwapi.h>
+
+namespace WindowsService
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	//////////////////////////////////////////////////////////////////////////
+	SERVICE_STATUS_HANDLE	g_SvcStatusHandle;							// 服务句柄;
+	SERVICE_STATUS			g_SvcStatus;								// 服务状态;
+	HANDLE					g_hCtrlSvc = NULL;							// 服务控制事件;												
+	TCHAR					g_szlpSvrDescription[MAX_PATH] = _T("");	// 服务描述	;
+	TCHAR					g_szSvcName[MAX_PATH] = _T("");				// 服务名称;
+	WorkStartCallback		g_lpStartWorkCallBack = NULL;				// 开启工作者;
+	WorkEndofCallback		g_lpEndofWorkCallBack = NULL;				// 结束工作者;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	int InitWinSock()
+	{
+		WORD	wVersionRequested;	
+		WSADATA	wsaData;			
+		int		nErrCode;			
+
+		wVersionRequested = MAKEWORD(2, 2);	
+		nErrCode = WSAStartup( wVersionRequested, &wsaData );
+		if ( 0 != nErrCode ) 
+			return -1;
+
+		return 0;
+	}
+
+	/************************************************************************/
+	/*  函数:InitSvcVar;
+	/*  描述:初始化服务变量;
+	/*  参数:;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void InitSvcVar()
+	{
+		g_SvcStatusHandle = NULL;
+		g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; // | SERVICE_INTERACTIVE_PROCESS与桌面交互;
+		g_SvcStatus.dwCurrentState = SERVICE_STOPPED;
+		g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+		g_SvcStatus.dwWin32ExitCode = 0;
+		g_SvcStatus.dwServiceSpecificExitCode = 0;
+		g_SvcStatus.dwCheckPoint = 0;
+		g_SvcStatus.dwWaitHint = 0;
+	}
+
+	/************************************************************************/
+	/*  函数:IsSvcInstalled;
+	/*  描述:判断服务是否安装;
+	/*  参数:;
+	/*  返回:若服务已安装返回TRUE,否则返回FALSE;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL IsSvcInstalled()
+	{
+		BOOL bResult = FALSE;
+		// 打开服务控制管理器;
+		SC_HANDLE schSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+
+		if (schSCM != NULL)
+		{// 打开服务;
+			SC_HANDLE schSvc = ::OpenService(schSCM, g_szSvcName, SERVICE_QUERY_CONFIG);
+			if (schSvc != NULL)
+			{
+				bResult = TRUE;
+				::CloseServiceHandle(schSvc);
+			}
+			::CloseServiceHandle(schSCM);
+		}
+
+		return bResult;
+	}
+
+	/************************************************************************/
+	/*  函数:SvcInstall;
+	/*  描述:安装服务;
+	/*  参数:;
+	/*  返回:安装成功返回TRUE,否则返回FALSE;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL SvcInstall()
+	{
+		// 获取服务程序的绝对路径;
+		TCHAR szFilePath[MAX_PATH];
+		if ( 0 == ::GetModuleFileName(NULL, szFilePath, MAX_PATH) )
+		{
+			_tprintf_s(_T("Cannot Install Service (%d)\n"), GetLastError());
+			return FALSE;
+		}
+
+		// 打开服务控制管理器,获取SCM数据库句柄;
+		SC_HANDLE schSCM = ::OpenSCManager(
+			NULL,						// 本地计算机;
+			NULL,						// ServicesActive database;
+			SC_MANAGER_ALL_ACCESS		// 所有权限;
+			);
+
+		if (schSCM == NULL)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return FALSE;
+		}
+
+		// 创建服务;
+		SC_HANDLE schSvc = ::CreateService(
+			schSCM,							// SCM数据库;
+			g_szSvcName,					// 服务名称;
+			g_szSvcName,					// 服务描述;
+			SERVICE_ALL_ACCESS,				// 需要的访问权限;
+			SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,		// 服务类型;
+			SERVICE_AUTO_START, //SERVICE_DEMAND_START,		// 启动类型;
+			SERVICE_ERROR_NORMAL,			// 错误控制类型;
+			szFilePath,						// 服务程序路径;
+			NULL,							// 无加载顺序组;
+			NULL,							// 无标签标识;
+			_T(""),							// 无依赖;
+			NULL,							// 本地系统账号;
+			NULL							// 无密码(no password);
+			);
+
+		if ( schSvc == NULL )
+		{
+			_tprintf_s(_T("CreateService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSvc);
+			return FALSE;
+		}
+
+		// 设置服务的描述;
+		SERVICE_DESCRIPTION ServiceDesc;    
+		ServiceDesc.lpDescription  =  g_szlpSvrDescription;   
+		::ChangeServiceConfig2(schSvc,   SERVICE_CONFIG_DESCRIPTION,   &ServiceDesc);   
+
+		// 释放资源;
+		::CloseServiceHandle(schSvc);
+		::CloseServiceHandle(schSCM);
+
+		return TRUE;
+	}
+
+	/************************************************************************/
+	/*  函数:ServiceMain;
+	/*  描述:服务入口函数;
+	/*  参数:;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WINAPI ServiceMain()
+	{
+		// 注册服务的控制函数;
+		g_SvcStatusHandle = RegisterServiceCtrlHandler(g_szSvcName, SvcCtrlHandler);
+		if (g_SvcStatusHandle == NULL)
+		{
+			SvcReportEvent(_T("Handler not installed"));
+			return;
+		}
+
+		// 在这里设置服务状态;
+		g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+		g_SvcStatus.dwServiceSpecificExitCode = 0;
+
+		// 注册成功后向SCM报告服务状态信息,因为服务还没初始化完成;
+		// 所以当前服务状态为SERVICE_START_PENDING ;
+		ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000); // 处理第一个事件大约需要3秒钟;
+
+		//////////////////////////////////////////////////////////////////////////
+		// 开始初始化服务;
+		g_hCtrlSvc = ::CreateEvent(	NULL,TRUE, FALSE, _T("CtrlService::g_hCtrlSvc"));
+		if (g_hCtrlSvc == NULL)
+		{
+			// 向SCM报告服务已停止;
+			ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 0);
+			return;
+		}
+
+		// 向SCM报告服务正在运行;
+		ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
+
+		// 开启工作者;
+		if ( g_lpStartWorkCallBack )
+			g_lpStartWorkCallBack();
+
+		// 线程中的处理函数运行结束后返回ServiceMain(),
+		// ServiceMain()调用WaitForSingleObject,
+		// 因为服务被停止之前ServiceMain()不会结束 
+		WaitForSingleObject(g_hCtrlSvc,INFINITE); // INFINITE表示无限等待,等待SCM的信号;
+		CloseHandle(g_hCtrlSvc);
+
+		// 结束工作者;
+		if ( g_lpEndofWorkCallBack )
+			g_lpEndofWorkCallBack();
+
+		SvcReportEvent(_T("Service stopped"));
+
+		// 向SCM报告服务已停止工作;
+		ReportSvcStatus(SERVICE_STOPPED,NO_ERROR,0,0,0); 
+	}
+
+	/************************************************************************/
+	/*  函数:SvcCtrlHandler;
+	/*  描述:每当有控制码发送给服务时被SCM调用;
+	/*  参数:;
+	/*  	[IN] dwControlCode:发送给服务的控制码;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WINAPI SvcCtrlHandler(IN DWORD dwControlCode)
+	{
+		BOOL bsucc = FALSE;
+		switch (dwControlCode)
+		{
+		case SERVICE_CONTROL_SHUTDOWN:		// 关掉服务;
+		case SERVICE_CONTROL_STOP:			// 停止服务;
+			bsucc = ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 0);
+			if (bsucc)
+				KillService();
+			break;
+		case SERVICE_CONTROL_PAUSE:
+			// 暂停服务;
+			break;
+		case SERVICE_CONTROL_CONTINUE:
+			// 恢复被暂停的服务;
+			break;
+		case SERVICE_CONTROL_INTERROGATE:
+			break;
+		default:
+			SvcReportEvent(_T("Bad service request"));
+		}
+	}
+
+	/************************************************************************/
+	/*  函数:ReportSvcStatus;
+	/*  描述:设置当前服务状态,并将其报告给SCM;
+	/*  参数:;
+	/*  	[IN] dwCurrentState:服务当前状态(详情见 SERVICE_STATUS);
+	/*  	[IN] dwWin32ExitCode:系统返回服务的错误码;
+	/*  	[IN] dwServiceSpecificExitCode:用户自定义的服务错误码;
+	/*  	[OUT] dwCheckPoint:;
+	/*  	[IN/OUT] dwWaitHint:挂起操作的估计用时;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
+	{
+		BOOL bSuccess; 
+		// 填充SERVICE_STATUS结构体,以便用于设置服务状态;
+		g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;		// 表示我们的服务是独占一个进程的服务 ;
+		g_SvcStatus.dwCurrentState = dwCurrentState;				// 当前服务状态;
+		g_SvcStatus.dwWaitHint = dwWaitHint;
+
+		if( dwCurrentState == SERVICE_START_PENDING )  
+		{ 
+			g_SvcStatus.dwControlsAccepted = 0; // 不接受任何控制通知; 
+		} 
+		else 
+		{ 
+			// 通知 SCM 服务接受哪个控制通知:这里允许停止、关机、暂停继续;
+			g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ; //|SERVICE_ACCEPT_PAUSE_CONTINUE;
+		} 
+
+		if ( (dwCurrentState == SERVICE_RUNNING ) || ( dwCurrentState == SERVICE_STOPPED ) )
+			g_SvcStatus.dwCheckPoint = 0;
+		else
+			g_SvcStatus.dwCheckPoint = dwCheckPoint++;
+
+		// dwServiceSpecificExitCode在你终止服务并报告退出细节时很有用。
+		// 初始化服务时并不退出,因此值为 0; 
+		if(dwServiceSpecificExitCode == 0) 
+		{ 
+			g_SvcStatus.dwWin32ExitCode = dwWin32ExitCode; 
+		} 
+		else 
+		{ 
+			g_SvcStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; //用户自定义错误代码;
+		} 
+		g_SvcStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode; 
+
+		//设置好nServiceStatus后,向SCM报告服务状态,非0表示成功,0表示失败;
+		bSuccess = SetServiceStatus( g_SvcStatusHandle,&g_SvcStatus);  
+		if( !bSuccess )
+		{ 
+			SvcReportEvent(_T("Set Service Status failed (%d) "), GetLastError());
+			KillService(); 
+			return FALSE;  
+		} 
+		else 
+			return TRUE;
+	}
+
+	// 结束服务;
+	void KillService()
+	{
+		//LOG4C((LOG_NOTICE,"KillService."));
+		SetEvent(g_hCtrlSvc); //如果操作成功,则返回非零值,否则为0。设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
+		//ReportStatusToSCMgr(SERVICE_STOPPED,NO_ERROR,0,0,0); 
+	}
+
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void SvcReportEvent(IN LPCTSTR pFormat, ...)
+	{
+		TCHAR    szReport[MAX_PATH] = {0};
+		HANDLE   hEventSource;
+		LPCTSTR  lpszStrings[2];
+		va_list  pArg = NULL;
+
+		va_start(pArg, pFormat);
+		StringCchVPrintf(szReport, MAX_PATH, pFormat, pArg);
+		va_end(pArg);
+
+		hEventSource = RegisterEventSource(NULL, g_szSvcName);
+		if (hEventSource != NULL)
+		{
+			lpszStrings[0] = g_szSvcName;
+			lpszStrings[1] = szReport;
+
+			ReportEvent(
+				hEventSource,					// 事件日志句柄;
+				EVENTLOG_INFORMATION_TYPE,		// 事件类型;
+				0,								// 事件类别;
+				0/*SVC_ERROR*/,					// 事件标识;
+				NULL,							// 无安全标识;
+				2,								// lpszStrings数组大小;
+				0,								// 无二进制数据;
+				lpszStrings,					// 字符串数组;
+				NULL							// 无二进制数据;
+				);
+
+			DeregisterEventSource(hEventSource);
+		}
+	}
+
+	/************************************************************************/
+	/*  函数:StartSvc;
+	/*  描述:启动服务;
+	/*  参数:;
+	/*  	[IN] lpSvcName:要打开的服务名称;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void StartSvc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要启动的服务名空\n"));
+			return;
+		}
+
+		SC_HANDLE schSCM;
+		SC_HANDLE schService;
+		SERVICE_STATUS_PROCESS ssStatus; 
+		DWORD dwOldCheckPoint; 
+		DWORD dwStartTickCount;
+		DWORD dwWaitTime;
+		DWORD dwBytesNeeded;
+
+		// 打开服务管理器; 
+		schSCM = OpenSCManager( 
+			NULL,                    // NULL表示要地计算机;
+			NULL,                    // NULl表示服务活动数据库; 
+			SC_MANAGER_ALL_ACCESS);  // 全部管理权限; 
+
+		if (NULL == schSCM) 
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 获取服务句柄;
+		schService = OpenService( 
+			schSCM,					// SCM数据库; 
+			lpSvcName,				// 服务名称;
+			SERVICE_ALL_ACCESS);	// 全部权限;
+
+		if (schService == NULL)
+		{ 
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError()); 
+			CloseServiceHandle(schSCM);
+			return;
+		}    
+
+		// 启动服务前,检查服务状态以防服务不是停止的状态;
+		if (!QueryServiceStatusEx( 
+			schService,                     // 服务句柄; 
+			SC_STATUS_PROCESS_INFO,         // 要查询的服务状态类型;
+			(LPBYTE) &ssStatus,             // 服务状态对象地址;
+			sizeof(SERVICE_STATUS_PROCESS), // 结构体大小;
+			&dwBytesNeeded ) )              // size needed if buffer is too small
+		{
+			_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schService); 
+			CloseServiceHandle(schSCM);
+			return; 
+		}
+
+		// Check if the service is already running. It would be possible 
+		// to stop the service here, but for simplicity this example just returns. 
+		// 如果服务已经在运行,检查;可以在这里停止服务,简单起见,这里只返回;
+		if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
+		{
+			_tprintf_s(_T("Cannot start the service because it is already running\n"));
+			CloseServiceHandle(schService); 
+			CloseServiceHandle(schSCM);
+			return; 
+		}
+
+		// Save the tick count and initial checkpoint.
+		// 保持计数值并初始化检查点;
+		dwStartTickCount = GetTickCount();
+		dwOldCheckPoint = ssStatus.dwCheckPoint;
+
+		// Wait for the service to stop before attempting to start it.
+		// 在尝试启动服务前,等待服务停止;
+		while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
+		{
+			// Do not wait longer than the wait hint. A good interval is 
+			// one-tenth of the wait hint but not less than 1 second  
+			// and not more than 10 seconds. 
+
+			dwWaitTime = ssStatus.dwWaitHint / 10;
+
+			if( dwWaitTime < 1000 )
+				dwWaitTime = 1000;
+			else if ( dwWaitTime > 10000 )
+				dwWaitTime = 10000;
+
+			Sleep( dwWaitTime );
+
+			// Check the status until the service is no longer stop pending. 
+			// 检测状态直到服务不再停止等待;
+			if (!QueryServiceStatusEx( 
+				schService,                     // handle to service 
+				SC_STATUS_PROCESS_INFO,         // information level
+				(LPBYTE) &ssStatus,             // address of structure
+				sizeof(SERVICE_STATUS_PROCESS), // size of structure
+				&dwBytesNeeded ) )              // size needed if buffer is too small
+			{
+				_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+				CloseServiceHandle(schService); 
+				CloseServiceHandle(schSCM);
+				return; 
+			}
+
+			if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
+			{
+				// Continue to wait and check.
+				// 继续等待并检测;
+				dwStartTickCount = GetTickCount();
+				dwOldCheckPoint = ssStatus.dwCheckPoint;
+			}
+			else
+			{
+				if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
+				{
+					_tprintf_s(_T("Timeout waiting for service to stop\n"));
+					CloseServiceHandle(schService); 
+					CloseServiceHandle(schSCM);
+					return; 
+				}
+			}
+		}
+
+		// Attempt to start the service.
+		// 尝试启动服务;
+		if (!StartService(
+			schService,  // handle to service 
+			0,           // number of arguments 
+			NULL) )      // no arguments 
+		{
+			_tprintf_s(_T("StartService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schService); 
+			CloseServiceHandle(schSCM);
+			return; 
+		}
+		else printf("Service start pending...\n"); 
+
+		// Check the status until the service is no longer start pending. 
+		// 检测服务状态直到服务不再启动挂起操作;
+		if (!QueryServiceStatusEx( 
+			schService,                     // handle to service 
+			SC_STATUS_PROCESS_INFO,         // info level
+			(LPBYTE) &ssStatus,             // address of structure
+			sizeof(SERVICE_STATUS_PROCESS), // size of structure
+			&dwBytesNeeded ) )              // if buffer too small
+		{
+			_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schService); 
+			CloseServiceHandle(schSCM);
+			return; 
+		}
+
+		// Save the tick count and initial checkpoint.
+		dwStartTickCount = GetTickCount();
+		dwOldCheckPoint = ssStatus.dwCheckPoint;
+
+		while (ssStatus.dwCurrentState == SERVICE_START_PENDING) 
+		{ 
+			// Do not wait longer than the wait hint. A good interval is 
+			// one-tenth the wait hint, but no less than 1 second and no 
+			// more than 10 seconds. 
+
+			dwWaitTime = ssStatus.dwWaitHint / 10;
+
+			if( dwWaitTime < 1000 )
+				dwWaitTime = 1000;
+			else if ( dwWaitTime > 10000 )
+				dwWaitTime = 10000;
+
+			Sleep( dwWaitTime );
+
+			// Check the status again. 
+			if (!QueryServiceStatusEx( 
+				schService,             // handle to service 
+				SC_STATUS_PROCESS_INFO, // info level
+				(LPBYTE) &ssStatus,             // address of structure
+				sizeof(SERVICE_STATUS_PROCESS), // size of structure
+				&dwBytesNeeded ) )              // if buffer too small
+			{
+				_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+				break; 
+			}
+
+			if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
+			{
+				// Continue to wait and check.
+				dwStartTickCount = GetTickCount();
+				dwOldCheckPoint = ssStatus.dwCheckPoint;
+			}
+			else
+			{
+				if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
+				{
+					// No progress made within the wait hint.
+					break;
+				}
+			}
+		} 
+
+		// Determine whether the service is running.
+		if (ssStatus.dwCurrentState == SERVICE_RUNNING) 
+		{
+			_tprintf_s(_T("Service started successfully.\n")); 
+		}
+		else 
+		{ 
+			_tprintf_s(_T("Service not started. \n"));
+			_tprintf_s(_T("  Current State: %d\n"), ssStatus.dwCurrentState); 
+			_tprintf_s(_T("  Exit Code: %d\n"), ssStatus.dwWin32ExitCode); 
+			_tprintf_s(_T("  Check Point: %d\n"), ssStatus.dwCheckPoint); 
+			_tprintf_s(_T("  Wait Hint: %d\n"), ssStatus.dwWaitHint); 
+		} 
+
+		CloseServiceHandle(schService); 
+		CloseServiceHandle(schSCM);
+
+	}
+
+	/************************************************************************/
+	/*  函数:UpdateSvcDacl;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void UpdateSvcDacl(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+			return;
+
+		EXPLICIT_ACCESS      ea;
+		SECURITY_DESCRIPTOR  sd;
+		PSECURITY_DESCRIPTOR psd            = NULL;
+		PACL                 pacl           = NULL;
+		PACL                 pNewAcl        = NULL;
+		BOOL                 bDaclPresent   = FALSE;
+		BOOL                 bDaclDefaulted = FALSE;
+		DWORD                dwError        = 0;
+		DWORD                dwSize         = 0;
+		DWORD                dwBytesNeeded  = 0;
+
+		SC_HANDLE schSCManager;
+		SC_HANDLE schService;
+
+		// 获取SCM数据库的句柄值;
+		schSCManager = OpenSCManager( 
+			NULL,                    // local computer
+			NULL,                    // ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCManager) 
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// Get a handle to the service
+
+		schService = OpenService( 
+			schSCManager,              // SCManager database 
+			lpSvcName,                 // name of service 
+			READ_CONTROL | WRITE_DAC); // access
+
+		if (schService == NULL)
+		{ 
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError()); 
+			CloseServiceHandle(schSCManager);
+			return;
+		}    
+
+		// Get the current security descriptor.
+		// 获取当前服务的安全描述符;
+		if (!QueryServiceObjectSecurity(schService,
+			DACL_SECURITY_INFORMATION, 
+			&psd,           // using NULL does not work on all versions
+			0, 
+			&dwBytesNeeded))
+		{
+			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+			{
+				dwSize = dwBytesNeeded;
+				psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
+				if (psd == NULL)
+				{
+					// Note: HeapAlloc does not support GetLastError.
+					_tprintf_s(_T("HeapAlloc failed\n"));
+					goto dacl_cleanup;
+				}
+
+				if (!QueryServiceObjectSecurity(schService,
+					DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
+				{
+					_tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
+					goto dacl_cleanup;
+				}
+			}
+			else 
+			{
+				_tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
+				goto dacl_cleanup;
+			}
+		}
+
+		// Get the DACL.
+
+		if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
+			&bDaclDefaulted))
+		{
+			_tprintf_s(_T("GetSecurityDescriptorDacl failed(%d)\n"), GetLastError());
+			goto dacl_cleanup;
+		}
+
+		// Build the ACE.
+
+		BuildExplicitAccessWithName(&ea, TEXT("GUEST"),
+			SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
+			SET_ACCESS, NO_INHERITANCE);
+
+		dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
+		if (dwError != ERROR_SUCCESS)
+		{
+			printf("SetEntriesInAcl failed(%d)\n", dwError);
+			goto dacl_cleanup;
+		}
+
+		// Initialize a new security descriptor.
+
+		if (!InitializeSecurityDescriptor(&sd, 
+			SECURITY_DESCRIPTOR_REVISION))
+		{
+			printf("InitializeSecurityDescriptor failed(%d)\n", GetLastError());
+			goto dacl_cleanup;
+		}
+
+		// Set the new DACL in the security descriptor.
+
+		if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
+		{
+			printf("SetSecurityDescriptorDacl failed(%d)\n", GetLastError());
+			goto dacl_cleanup;
+		}
+
+		// Set the new DACL for the service object.
+
+		if (!SetServiceObjectSecurity(schService, 
+			DACL_SECURITY_INFORMATION, &sd))
+		{
+			printf("SetServiceObjectSecurity failed(%d)\n", GetLastError());
+			goto dacl_cleanup;
+		}
+		else printf("Service DACL updated successfully\n");
+
+dacl_cleanup:
+		CloseServiceHandle(schSCManager);
+		CloseServiceHandle(schService);
+
+		if(NULL != pNewAcl)
+			LocalFree((HLOCAL)pNewAcl);
+		if(NULL != psd)
+			HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
+
+	}
+
+	void DoStopSvc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("指定要停止的服务名无效\n"));
+			return;
+		}
+		SERVICE_STATUS_PROCESS ssp;
+		DWORD dwStartTime = GetTickCount();
+		DWORD dwBytesNeeded;
+		DWORD dwTimeout = 30000; // 30-second time-out
+		DWORD dwWaitTime;
+
+		SC_HANDLE schSCManager;
+		SC_HANDLE schService;
+		// Get a handle to the SCM database. 
+
+		schSCManager = OpenSCManager( 
+			NULL,                    // local computer
+			NULL,                    // ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCManager) 
+		{
+			printf("OpenSCManager failed (%d)\n", GetLastError());
+			return;
+		}
+
+		// Get a handle to the service.
+
+		schService = OpenService( 
+			schSCManager,         // SCM database 
+			lpSvcName,            // name of service 
+			SERVICE_STOP | 
+			SERVICE_QUERY_STATUS | 
+			SERVICE_ENUMERATE_DEPENDENTS);  
+
+		if (schService == NULL)
+		{ 
+			printf("OpenService failed (%d)\n", GetLastError()); 
+			CloseServiceHandle(schSCManager);
+			return;
+		}    
+
+		// Make sure the service is not already stopped.
+
+		if ( !QueryServiceStatusEx( 
+			schService, 
+			SC_STATUS_PROCESS_INFO,
+			(LPBYTE)&ssp, 
+			sizeof(SERVICE_STATUS_PROCESS),
+			&dwBytesNeeded ) )
+		{
+			printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); 
+			goto stop_cleanup;
+		}
+
+		if ( ssp.dwCurrentState == SERVICE_STOPPED )
+		{
+			printf("Service is already stopped.\n");
+			goto stop_cleanup;
+		}
+
+		// If a stop is pending, wait for it.
+
+		while ( ssp.dwCurrentState == SERVICE_STOP_PENDING ) 
+		{
+			printf("Service stop pending...\n");
+
+			// Do not wait longer than the wait hint. A good interval is 
+			// one-tenth of the wait hint but not less than 1 second  
+			// and not more than 10 seconds. 
+
+			dwWaitTime = ssp.dwWaitHint / 10;
+
+			if( dwWaitTime < 1000 )
+				dwWaitTime = 1000;
+			else if ( dwWaitTime > 10000 )
+				dwWaitTime = 10000;
+
+			Sleep( dwWaitTime );
+
+			if ( !QueryServiceStatusEx( 
+				schService, 
+				SC_STATUS_PROCESS_INFO,
+				(LPBYTE)&ssp, 
+				sizeof(SERVICE_STATUS_PROCESS),
+				&dwBytesNeeded ) )
+			{
+				printf("QueryServiceStatusEx failed (%d)\n", GetLastError()); 
+				goto stop_cleanup;
+			}
+
+			if ( ssp.dwCurrentState == SERVICE_STOPPED )
+			{
+				printf("Service stopped successfully.\n");
+				goto stop_cleanup;
+			}
+
+			if ( GetTickCount() - dwStartTime > dwTimeout )
+			{
+				printf("Service stop timed out.\n");
+				goto stop_cleanup;
+			}
+		}
+
+		// If the service is running, dependencies must be stopped first.
+
+		StopDependentServices();
+
+		// Send a stop code to the service.
+
+		if ( !ControlService( 
+			schService, 
+			SERVICE_CONTROL_STOP, 
+			(LPSERVICE_STATUS) &ssp ) )
+		{
+			printf( "ControlService failed (%d)\n", GetLastError() );
+			goto stop_cleanup;
+		}
+
+		// Wait for the service to stop.
+
+		while ( ssp.dwCurrentState != SERVICE_STOPPED ) 
+		{
+			Sleep( ssp.dwWaitHint );
+			if ( !QueryServiceStatusEx( 
+				schService, 
+				SC_STATUS_PROCESS_INFO,
+				(LPBYTE)&ssp, 
+				sizeof(SERVICE_STATUS_PROCESS),
+				&dwBytesNeeded ) )
+			{
+				printf( "QueryServiceStatusEx failed (%d)\n", GetLastError() );
+				goto stop_cleanup;
+			}
+
+			if ( ssp.dwCurrentState == SERVICE_STOPPED )
+				break;
+
+			if ( GetTickCount() - dwStartTime > dwTimeout )
+			{
+				printf( "Wait timed out\n" );
+				goto stop_cleanup;
+			}
+		}
+		printf("Service stopped successfully\n");
+
+stop_cleanup:
+		CloseServiceHandle(schService); 
+		CloseServiceHandle(schSCManager);
+
+	}
+
+	BOOL StopDependentServices()
+	{
+		DWORD i;
+		DWORD dwBytesNeeded;
+		DWORD dwCount;
+
+		LPENUM_SERVICE_STATUS   lpDependencies = NULL;
+		ENUM_SERVICE_STATUS     ess;
+		SC_HANDLE               hDepService;
+		SERVICE_STATUS_PROCESS  ssp;
+
+		DWORD dwStartTime = GetTickCount();
+		DWORD dwTimeout = 30000; // 30-second time-out
+
+		SC_HANDLE schSCManager = NULL;
+		SC_HANDLE schService = NULL;
+
+		// Pass a zero-length buffer to get the required buffer size.
+		if ( EnumDependentServices( schService, SERVICE_ACTIVE, 
+			lpDependencies, 0, &dwBytesNeeded, &dwCount ) ) 
+		{
+			// If the Enum call succeeds, then there are no dependent
+			// services, so do nothing.
+			return TRUE;
+		} 
+		else 
+		{
+			if ( GetLastError() != ERROR_MORE_DATA )
+				return FALSE; // Unexpected error
+
+			// Allocate a buffer for the dependencies.
+			lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc( 
+				GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );
+
+			if ( !lpDependencies )
+				return FALSE;
+
+			__try {
+				// Enumerate the dependencies.
+				if ( !EnumDependentServices( schService, SERVICE_ACTIVE, 
+					lpDependencies, dwBytesNeeded, &dwBytesNeeded,
+					&dwCount ) )
+					return FALSE;
+
+				for ( i = 0; i < dwCount; i++ ) 
+				{
+					ess = *(lpDependencies + i);
+					// Open the service.
+					hDepService = OpenService( schSCManager, 
+						ess.lpServiceName, 
+						SERVICE_STOP | SERVICE_QUERY_STATUS );
+
+					if ( !hDepService )
+						return FALSE;
+
+					__try {
+						// Send a stop code.
+						if ( !ControlService( hDepService, 
+							SERVICE_CONTROL_STOP,
+							(LPSERVICE_STATUS) &ssp ) )
+							return FALSE;
+
+						// Wait for the service to stop.
+						while ( ssp.dwCurrentState != SERVICE_STOPPED ) 
+						{
+							Sleep( ssp.dwWaitHint );
+							if ( !QueryServiceStatusEx( 
+								hDepService, 
+								SC_STATUS_PROCESS_INFO,
+								(LPBYTE)&ssp, 
+								sizeof(SERVICE_STATUS_PROCESS),
+								&dwBytesNeeded ) )
+								return FALSE;
+
+							if ( ssp.dwCurrentState == SERVICE_STOPPED )
+								break;
+
+							if ( GetTickCount() - dwStartTime > dwTimeout )
+								return FALSE;
+						}
+					} 
+					__finally 
+					{
+						// Always release the service handle.
+						CloseServiceHandle( hDepService );
+					}
+				}
+			} 
+			__finally 
+			{
+				// Always free the enumeration buffer.
+				HeapFree( GetProcessHeap(), 0, lpDependencies );
+			}
+		} 
+		return TRUE;
+
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoQuerySvc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要查询的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE hSCM;
+		SC_HANDLE hSvc;
+		LPQUERY_SERVICE_CONFIG lpsc;
+		LPSERVICE_DESCRIPTION lpsd;
+		DWORD dwBytesNeeded, cbBfuSize, dwError;
+
+		// 获取SCM句柄;
+		hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
+		if ( hSCM == NULL )
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 获取服务句柄;
+		hSvc = OpenService( 
+			hSCM, 
+			lpSvcName, 
+			SERVICE_QUERY_CONFIG			// 需要查询设置的权限;
+			);
+		if ( hSvc == NULL )
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(hSCM);
+			return;
+		}
+
+		// 获取服务设置信息;
+		if ( !QueryServiceConfig( hSvc, NULL, 0, &dwBytesNeeded) )
+		{
+			dwError = GetLastError();
+			if ( ERROR_INSUFFICIENT_BUFFER == dwError )
+			{
+				cbBfuSize = dwBytesNeeded;
+				lpsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbBfuSize);
+			}
+			else
+			{
+				_tprintf_s(_T("QueryServiceConfig failed (%d)\n"), dwError);
+				goto cleanup;
+			}
+		}
+
+		if ( !QueryServiceConfig(hSvc, lpsc, cbBfuSize, &dwBytesNeeded) )
+		{
+			_tprintf_s(_T("QuerySericeConfig failed (%d)\n"), GetLastError());
+			goto cleanup;
+		}
+
+		if ( !QueryServiceConfig2( hSvc, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded) )
+		{
+			dwError = GetLastError();
+			if ( ERROR_INSUFFICIENT_BUFFER == dwError )
+			{
+				cbBfuSize = dwBytesNeeded;
+				lpsd = (LPSERVICE_DESCRIPTION)LocalAlloc(LMEM_FIXED, cbBfuSize);
+			}
+			else
+			{
+				_tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
+				goto cleanup;
+			}
+		}
+
+		if ( !QueryServiceConfig2( hSvc, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)lpsd, cbBfuSize, &dwBytesNeeded) )
+		{
+			_tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
+			goto cleanup;
+		}
+
+		//////////////////////////////////////////////////////////////////////////
+		// 查询成功,组织要返回的东西;
+		_tprintf(TEXT("%s configuration: \n"), g_szSvcName);
+		_tprintf(TEXT("  Type: 0x%x\n"), lpsc->dwServiceType);
+		_tprintf(TEXT("  Start Type: 0x%x\n"), lpsc->dwStartType);
+		_tprintf(TEXT("  Error Control: 0x%x\n"), lpsc->dwErrorControl);
+		_tprintf(TEXT("  Binary path: %s\n"), lpsc->lpBinaryPathName);
+		_tprintf(TEXT("  Account: %s\n"), lpsc->lpServiceStartName);
+
+		if (lpsd->lpDescription != NULL && lstrcmp(lpsd->lpDescription, TEXT("")) != 0)
+			_tprintf(TEXT("  Description: %s\n"), lpsd->lpDescription);
+		if (lpsc->lpLoadOrderGroup != NULL && lstrcmp(lpsc->lpLoadOrderGroup, TEXT("")) != 0)
+			_tprintf(TEXT("  Load order group: %s\n"), lpsc->lpLoadOrderGroup);
+		if (lpsc->dwTagId != 0)
+			_tprintf(TEXT("  Tag ID: %d\n"), lpsc->dwTagId);
+		if (lpsc->lpDependencies != NULL && lstrcmp(lpsc->lpDependencies, TEXT("")) != 0)
+			_tprintf(TEXT("  Dependencies: %s\n"), lpsc->lpDependencies);
+
+		// 释放资源;
+		LocalFree(lpsc);
+		LocalFree(lpsd);
+
+cleanup:
+		CloseServiceHandle(hSvc);
+		CloseServiceHandle(hSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoDisableSvc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要禁用的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+
+		// 打开SCM;
+		schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+		if ( schSCM == NULL )
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 获取服务句柄;
+		schSvc = OpenService(schSCM, lpSvcName, SERVICE_CHANGE_CONFIG );
+		if ( schSvc == NULL )
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError()); 
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		if ( !ChangeServiceConfig(
+			schSvc,
+			SERVICE_NO_CHANGE, // service type: no change 
+			SERVICE_DISABLED,  // service start type 
+			SERVICE_NO_CHANGE, // error control: no change 
+			NULL,              // binary path: no change 
+			NULL,              // load order group: no change 
+			NULL,              // tag ID: no change 
+			NULL,              // dependencies: no change 
+			NULL,              // account name: no change 
+			NULL,              // password: no change 
+			NULL) )            // display name: no change
+		{
+			_tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError()); 
+		}
+
+		CloseServiceHandle(schSvc);
+		CloseServiceHandle(schSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoEnableSvc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要启用的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+
+		// Get a handle to the SCM database. 
+		// 获取SCM数据库句柄;
+		schSCM = OpenSCManager( 
+			NULL,                    // local computer
+			NULL,                    // ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCM) 
+		{
+			printf("OpenSCManager failed (%d)\n", GetLastError());
+			return;
+		}
+
+		// Get a handle to the service.
+		// 获取服务句柄值;
+		schSvc = OpenService( 
+			schSCM,						// SCM database 
+			lpSvcName,                // name of service 
+			SERVICE_CHANGE_CONFIG);		// need change config access 
+
+		if (schSvc == NULL)
+		{ 
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError()); 
+			CloseServiceHandle(schSCM);
+			return;
+		}    
+
+		// Change the service start type.
+		// 改变服务启动类型;
+		if (! ChangeServiceConfig( 
+			schSvc,					// 服务句柄; 
+			SERVICE_NO_CHANGE,     // service type: no change 
+			SERVICE_DEMAND_START,  // service start type 
+			SERVICE_NO_CHANGE,     // error control: no change 
+			NULL,                  // binary path: no change 
+			NULL,                  // load order group: no change 
+			NULL,                  // tag ID: no change 
+			NULL,                  // dependencies: no change 
+			NULL,                  // account name: no change 
+			NULL,                  // password: no change 
+			NULL) )                // display name: no change
+		{
+			_tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError()); 
+		}
+		else 
+		{
+			_tprintf_s(_T("Service enabled successfully.\n")); 
+		}
+
+		CloseServiceHandle(schSvc); 
+		CloseServiceHandle(schSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoUpdateSvcDesc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要更新描述的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+		SERVICE_DESCRIPTION sd;
+		LPTSTR szDesc = TEXT("This is a test description");
+
+		// Get a handle to the SCM database. 
+		// 获取SCM数据库句柄;
+		schSCM = OpenSCManager( 
+			NULL,                    // NULL表示本地计算机;
+			NULL,                    // NULL表示:ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCM) 
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// Get a handle to the service.
+		// 获取服务句柄值;
+		schSvc = OpenService( 
+			schSCM,						// SCM 数据库句柄; 
+			lpSvcName,                // 服务名称; 
+			SERVICE_CHANGE_CONFIG);     // need change config access 
+
+		if (schSvc == NULL)
+		{ 
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError()); 
+			CloseServiceHandle(schSCM);
+			return;
+		}    
+
+		// Change the service description.
+		// 改变服务描述;
+		sd.lpDescription = szDesc;
+
+		if( !ChangeServiceConfig2(
+			schSvc,						// 服务句柄;
+			SERVICE_CONFIG_DESCRIPTION, // 要改变的类型: description;
+			&sd) )                      // 新描述;
+		{
+			_tprintf_s(_T("ChangeServiceConfig2 failed\n"));
+		}
+		else 
+		{
+			_tprintf_s(_T("Service description updated successfully.\n"));
+		}
+
+		CloseServiceHandle(schSvc); 
+		CloseServiceHandle(schSCM);
+
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoDeleteSvc(IN LPCTSTR lpSvcName)
+	{
+		if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要删除的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+		SERVICE_STATUS ssStatus; 
+
+		// 打开服务管理器;
+		schSCM = OpenSCManager( 
+			NULL,                    // NULL表示本地计算机;
+			NULL,                    // NULL表示ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCM) 
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 打开服务;
+		schSvc = OpenService( 
+			schSCM,								// SCM database 
+			lpSvcName,							// name of service 
+			SERVICE_STOP|DELETE					// need delete access 
+			);				
+
+		if (schSvc == NULL)
+		{ 
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError()); 
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// 删除服务关,需要先停止服务;
+		if ( !::ControlService(schSvc, SERVICE_CONTROL_STOP, &ssStatus) )
+		{
+			_tprintf_s(_T("删除服务前停止服务失败 (%d)\n"), GetLastError()); 
+		}
+
+		// 删除服务;
+		if ( !DeleteService(schSvc) ) 
+		{
+			_tprintf_s(_T("DeleteService failed (%d)\n"), GetLastError()); 
+			SvcReportEvent(_T("Service could not be deleted"));
+		}
+		else
+		{
+			_tprintf_s(_T("Service deleted successfully\n")); 
+		}
+
+		CloseServiceHandle(schSvc); 
+		CloseServiceHandle(schSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:SetCallBack;
+	/*  描述:设置回调函数;
+	/*  参数:;
+	/*  	[IN] lpStartWorkCallBack:工作开始回调指针;
+	/*  	[IN] lpEndofWorkCallBack:工作结束回调指针;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void SetCallBack( IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack )
+	{
+		if ( g_lpStartWorkCallBack == NULL )
+			g_lpStartWorkCallBack = (WorkEndofCallback)lpStartWorkCallBack;
+
+		if ( g_lpEndofWorkCallBack == NULL )
+			g_lpEndofWorkCallBack = (WorkEndofCallback)lpEndofWorkCallBack;
+	}
+
+	/************************************************************************/
+	/*  函数:StartProcess;
+	/*  描述:在服务进程里,调用外部EXE;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL StartProcess( IN LPCTSTR lpExePath )
+	{
+#if 0
+		if( !lpExePath || !PathFileExists(lpExePath) )   
+		{   
+			return FALSE;   
+		} 
+
+		HANDLE hToken;   
+		if(!GetTokenByName(hToken,_T("EXPLORER.EXE")))   
+		{   
+			return   FALSE;   
+		}  
+
+		STARTUPINFO   si;   
+		PROCESS_INFORMATION   pi;   
+
+		ZeroMemory(&si, sizeof(STARTUPINFO));   
+		si.cb = sizeof(STARTUPINFO);   
+		si.lpDesktop = TEXT("winsta0\\default");   
+
+		BOOL bResult = CreateProcessAsUser(hToken,lpExePath,NULL,NULL,NULL, FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi); 
+		DWORD dwError = GetLastError();// 返回740错误,表示服务必须在Admin账号下运行才能创建成功;
+
+		//CreateProcessWithTokenW(hToken, )
+
+
+		CloseHandle(hToken);   
+		if(bResult)   
+		{   
+			// WriteLogAlways(_T("C:\\serverlog.txt"),_T("CreateProcessAsUser   ok"));
+		}   
+		else   
+		{   
+			//WriteLogAlways(_T("C:\\servererrlog.txt"),_T("CreateProcessAsUser   failed"));
+		} 
+#else
+		HANDLE hPtoken = NULL ;   
+		GetExplorerToken( &hPtoken ) ;  
+		//if(!GetTokenByName(hPtoken,_T("EXPLORER.EXE")))   
+		//{   
+		//	return   FALSE;   
+		//} 
+		PROCESS_INFORMATION pi;    
+		STARTUPINFOW si = { sizeof(STARTUPINFO),NULL,L"",NULL,0,0,0,0,0,0,0,STARTF_USESHOWWINDOW,0,0,NULL,0,0,0};     
+		si.wShowWindow = SW_SHOW;  
+		si.lpDesktop = NULL;  
+		ZeroMemory( &pi, sizeof(pi) );   
+
+		static HMODULE advapi32_dll = LoadLibraryW(L"advapi32.dll");
+		if(!advapi32_dll)
+			return FALSE;
+		
+		/*static F_CreateProcessWithTokenW f_CreateProcessWithTokenW = (F_CreateProcessWithTokenW)(
+			GetProcAddress(advapi32_dll,"CreateProcessWithTokenW"));
+		if (f_CreateProcessWithTokenW == NULL)
+			return ;
+*/
+		BOOL bResult = CreateProcessWithTokenW(hPtoken, LOGON_WITH_PROFILE, NULL, (LPWSTR)lpExePath, NULL, NULL, NULL, &si,&pi);
+
+		DWORD dwError = GetLastError();
+		Sleep(1000);  
+		CloseHandle( pi.hProcess );  
+
+		CloseHandle( pi.hThread );
+#endif
+		return   bResult;   
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL GetTokenByName( IN HANDLE &hToken, IN LPCTSTR lpName)
+	{
+		if(!lpName)   
+		{   
+			return FALSE;   
+		} 
+
+		BOOL bRet = FALSE;
+		HANDLE hProcessSnap = NULL;
+		PROCESSENTRY32 pe32 = {0};
+		hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+		if ( hProcessSnap == INVALID_HANDLE_VALUE )
+			return FALSE; 
+
+		pe32.dwSize = sizeof(PROCESSENTRY32);     
+		if (Process32First(hProcessSnap, &pe32))     
+		{       
+			do     
+			{   
+				CString exefile=pe32.szExeFile;
+				CString paraname = lpName;
+				if(!exefile.CompareNoCase(lpName))
+				{   
+					HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
+					bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
+					CloseHandle( hProcessSnap );
+					return bRet;   
+				}   
+			}     
+			while(Process32Next(hProcessSnap,&pe32));     
+			bRet = TRUE;     
+		}     
+		else     
+			bRet = FALSE;   
+
+		CloseHandle(hProcessSnap);     
+		return bRet; 
+	}
+
+	/************************************************************************/
+	/*  函数:;
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	// Jeff.Hacker. WINDOWS NT 以上的内核需要提权,才能对系统进行高级管理;
+	BOOL GetDebugPriv()
+	{
+		// 返回的访问令牌指针;
+		HANDLE	hToken;
+		// 接收所返回的制定特权名称的信息;
+		LUID	sedebugnameValue;
+		// 新特权信息的指针(结构体);
+		TOKEN_PRIVILEGES tkp;
+		DWORD	dwCurProcId = GetCurrentProcessId();
+		// 要修改访问权限的进程句柄;
+		HANDLE	hCurProc;
+		hCurProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurProcId);
+
+		if (!::OpenProcessToken(hCurProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		{
+			//ShowSystemErrorInfo(_T("升级包OpenProcessToken失败."),GetLastError());
+			return FALSE;
+		}
+
+		if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
+		{
+			//ShowSystemErrorInfo(_T("升级包LookupPrivilegeValue失败."),GetLastError());
+			CloseHandle(hToken);
+			return FALSE;
+		}
+
+		tkp.PrivilegeCount = 1;
+		tkp.Privileges[0].Luid = sedebugnameValue;
+		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+		if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
+		{
+			//ShowSystemErrorInfo(_T("升级包AdjustTokenPrivileges失败."),GetLastError());
+			CloseHandle(hToken);
+			return FALSE;
+		}
+
+		CloseHandle(hCurProc);
+		CloseHandle(hToken);
+		return TRUE;
+	}
+
+	DWORD GetExplorerToken(OUT HANDLE* phExplorerToken)
+	{
+		DWORD       dwStatus = ERROR_FILE_NOT_FOUND ;   
+		BOOL        bRet = FALSE ;  
+		HANDLE      hProcess = NULL ;  
+		HANDLE      hProcessSnap = NULL ;  
+		TCHAR       szExplorerPath[MAX_PATH] = { 0 };  
+		TCHAR       FileName[MAX_PATH] = { 0 };  
+		PROCESSENTRY32 pe32 = { 0 } ;  
+		__try  
+		{  
+			GetWindowsDirectory( szExplorerPath , MAX_PATH ) ;  
+			_tcscat_s( szExplorerPath , MAX_PATH, _T("\\Explorer.EXE") ) ;    
+			hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) ;   
+			if( hProcessSnap == INVALID_HANDLE_VALUE )    
+			{  
+				dwStatus = GetLastError() ;   
+				__leave ;  
+			}   
+			pe32.dwSize = sizeof( PROCESSENTRY32 ) ;   
+			if( !Process32First( hProcessSnap, &pe32 ))       
+			{     
+				dwStatus = GetLastError() ;   
+				__leave ;   
+			}   
+
+			int ii = 0;
+			do 
+			{      
+				hProcess = OpenProcess(PROCESS_ALL_ACCESS/*PROCESS_QUERY_INFORMATION*/,  FALSE, pe32.th32ProcessID ) ;  
+				if( NULL != hProcess )          
+				{   
+					ii++;
+					//if ( GetModuleFileNameEx(hProcess , NULL , FileName , MAX_PATH) )  
+					//{  
+						if( _tcsicmp( pe32.szExeFile , _T("Explorer.EXE") ) == 0 )   
+						{                                 
+							HANDLE  hToken ;  
+							if( OpenProcessToken( hProcess , TOKEN_DUPLICATE  , &hToken ))  
+							{       
+								HANDLE hNewToken = NULL;
+								DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken);
+								* phExplorerToken = hNewToken ;  
+								dwStatus = 0 ; 
+								CloseHandle(hToken);
+							}  
+							break ;  
+						}  
+					//}  
+					CloseHandle ( hProcess ) ;    
+					hProcess = NULL ;  
+				}  
+
+			} while( Process32Next( hProcessSnap, &pe32 )) ;  
+		}  
+		__finally   
+		{  
+			if( NULL != hProcess )  
+			{  
+				CloseHandle( hProcess ) ;  
+			}  
+			if( NULL != hProcessSnap )  
+			{  
+				CloseHandle ( hProcessSnap ) ;  
+			}  
+		}    
+		return dwStatus ;  
+	}
+};

+ 73 - 0
SATService/SATService/WindowService.h

@@ -0,0 +1,73 @@
+#ifndef __WINDOWS_SERVICE__
+#define __WINDOWS_SERVICE__
+
+#include <WinSvc.h>
+
+namespace WindowsService
+{
+	// 工作启动回调函数;
+	typedef void (CALLBACK *WorkStartCallback)();
+	// 工作结束回调函数;
+	typedef void (CALLBACK *WorkEndofCallback)();
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	//////////////////////////////////////////////////////////////////////////
+	extern SERVICE_STATUS_HANDLE	g_SvcStatusHandle;
+	extern SERVICE_STATUS			g_SvcStatus;
+	extern HANDLE					g_hCtrlSvc;							
+	extern TCHAR					g_szlpSvrDescription[MAX_PATH] ;
+	extern TCHAR					g_szSvcName[MAX_PATH];
+	extern WorkStartCallback		g_lpStartWorkCallBack;
+	extern WorkEndofCallback		g_lpEndofWorkCallBack;
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	// 初始化服务变量;
+	extern void InitSvcVar();
+	// 服务是否已安装;
+	extern BOOL IsSvcInstalled();
+	// 安装服务;
+	extern BOOL SvcInstall();
+	// windows服务程序入口函数;
+	extern void WINAPI ServiceMain();
+	// windows服务状态控制;
+	extern void WINAPI SvcCtrlHandler(IN DWORD dwControlCode);
+	// 初始化SOCKET库;
+	extern int InitWinSock();
+	// 服务日志事件;
+	extern void SvcReportEvent(IN LPCTSTR pFormat, ...);
+	// 向SCM报告服务状态;
+	extern BOOL ReportSvcStatus(
+		IN DWORD dwCurrentState, 
+		IN DWORD dwWin32ExitCode,
+		IN DWORD dwServiceSpecificExitCode, 
+		IN DWORD dwCheckPoint, 
+		IN DWORD dwWaitHint);
+
+	// 启动指定的服务;
+	extern void StartSvc(IN LPCTSTR lpSvcName);
+	extern void UpdateSvcDacl(IN LPCTSTR lpSvcName);
+	extern void DoStopSvc(IN LPCTSTR lpSvcName);
+	extern BOOL StopDependentServices();
+	// 查询服务状态;
+	extern void DoQuerySvc(IN LPCTSTR lpSvcName);
+	// 更新服务描述;
+	extern void DoUpdateSvcDesc(IN LPCTSTR lpSvcName);
+	extern void DoDisableSvc(IN LPCTSTR lpSvcName);
+	extern void DoEnableSvc(IN LPCTSTR lpSvcName);
+	extern void DoDeleteSvc(IN LPCTSTR lpSvcName);
+	extern void KillService();
+	// 设置回调函数指针;
+	extern void SetCallBack( IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack );
+	// 在服务进程里调用外部exe;
+	extern BOOL StartProcess( IN LPCTSTR lpExePath );
+	//
+	extern BOOL GetTokenByName( IN HANDLE &hToken, IN LPCTSTR lpName);
+	//
+	extern BOOL GetDebugPriv();
+	//
+	extern DWORD GetExplorerToken(OUT HANDLE* phExplorerToken);
+};
+
+
+#endif

BIN
SATService/SATService/main.ico


+ 2 - 1
SATService/SATService/stdafx.h

@@ -30,6 +30,7 @@
 #include <vector>
 #include "SATHTTP.h"
 #include "RunPython.h"
-
+#include "WindowService.h"
+#include "Global.h"
 
 // TODO: 在此处引用程序需要的其他头文件

+ 335 - 0
SATService/SATService/test.cpp

@@ -0,0 +1,335 @@
+#include "stdafx.h"
+#include <direct.h>
+
+bool MKDIR(LPCTSTR dir) 
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 创建目录;
+	int nleft = 0;
+	int nIndex = -1;
+	std::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 != std::string::npos)
+		{
+			if (_mkdir(strdir.substr(0, nIndex + nleft).c_str()) == -1 && (errno != EEXIST))
+			{
+				return false;
+			}
+
+			nleft += nIndex + 1;
+		}
+	} while (nIndex != -1);
+
+	return true;
+};
+
+__if_not_exists(NotifyJobStart)
+{
+	int NotifyJobStart(std::string url, const SATParameters::STNotifyJobStartReq &stNotifyJobStartReq, SATParameters::STNotifyJobStartResp &stNotifyJobStartResp) throw()
+	{
+		return SetResult(url, stNotifyJobStartReq, stNotifyJobStartResp);
+	}
+}
+
+__if_not_exists(ProcessJob)
+{
+	int ProcessJob(std::string url, const SATParameters::STJobProcessReq &stJobProcessReq, SATParameters::STJobProcessResp &stJobProcessResp) throw()
+	{
+		return SetResultList(url, stJobProcessReq, stJobProcessResp);
+	}
+}
+
+int test()
+{
+	//std::string host = "http://10.118.158.52:8580";//"http://10.118.158.198:8090";
+	std::string host = "http://10.118.158.198:8090";
+	SATParameters::STDevice stDevice;
+	stDevice.strStatus = "0";
+	stDevice.strDeviceSerial = "192.168.1.119:5555";
+	stDevice.strHardwareVersion = "MS6488";
+	stDevice.strManu = "MStar";
+	stDevice.strDeviceMac = "";
+	stDevice.strLastJobStartTime = "";
+	stDevice.strLastTimeBreak = "";
+	stDevice.strComments = "";
+	stDevice.strCPU = "";
+	stDevice.strSoftwareVersion = "1522659174";
+	stDevice.strPhoneNumber = "";
+	stDevice.strLastJobFinishTime = "";
+	stDevice.strMemory = "";
+	stDevice.strModel = "Generic Linux on tcl_ms6488_cn_64_n";
+	stDevice.strLastJob = "";
+	stDevice.strLastTimeConnected = "2019-12-16 10:16:01";
+	stDevice.strElectric = "";
+	// ##########################先登录##############################;
+	SATParameters::STLoginReq stLoginReq;
+	SATParameters::STLoginResp stLoginResp;
+	std::string url = host + "/btc_execute_se/ajaxInteractiveManage!executeLogin.action";
+	// 示例值;
+	stLoginReq.strUserName = "superAdmin";
+	stLoginReq.strStatus = "0";
+	stLoginReq.strDeleteStatus = "";
+	stLoginReq.strIP = "10.118.158.175";
+	stLoginReq.strStorage = "";
+	stLoginReq.strConnectTime = "";
+	stLoginReq.strExecuteName = "";
+	stLoginReq.strMAC = "40:16:7e:23:10:53";
+	stLoginReq.strDisconnectTime = "";
+	stLoginReq.strPassword = "123456";
+	stLoginReq.strCPU = "";
+
+	if ( !Login(url, stLoginReq, stLoginResp) )
+	{
+		system("pause");
+		return -1;
+	}
+
+	printf("登录返回:code=%s, msg=%s, str=%s, portCount=%d, companyid=%d, runnertoken=%s\n",
+		stLoginResp.strCode.c_str(),
+		stLoginResp.strMessage.c_str(),
+		stLoginResp.strStr.c_str(),
+		stLoginResp.nPortCount,
+		stLoginResp.nCompanyId,
+		stLoginResp.strRunnerToken.c_str()
+		);		
+
+	while(true)
+	{
+		// ##########################更新设备信息##############################;
+		SATParameters::STUpdateDeviceReq stUpdateDeviceReq;
+		SATParameters::STUpdateDeviceResp stUpdateDeviceResp;
+		__if_not_exists(url)
+		{			
+			std::string url = host + "/btc_execute_se/ajaxInteractiveManage!updateDeviceMessage.action";
+		}
+		__if_exists(url)
+		{
+			url = host + "/btc_execute_se/ajaxInteractiveManage!updateDeviceMessage.action";
+		}
+
+		stUpdateDeviceReq.strStatus = "0";
+		stUpdateDeviceReq.strUserName = "superAdmin";		
+		stUpdateDeviceReq.strIP = "10.118.158.175";
+		stUpdateDeviceReq.strStorage = "228092536KB";
+		stUpdateDeviceReq.strRunnerName = "SAT-Admin";
+		stUpdateDeviceReq.strMAC = "40:16:7e:23:10:53";
+		stUpdateDeviceReq.strReportType = "1";
+		stUpdateDeviceReq.strStartTime = "2019-12-16 19:15:30";
+		stUpdateDeviceReq.strMemory = "8938544KB";
+		stUpdateDeviceReq.strEndTime = "";
+		stUpdateDeviceReq.strCPU = "24.7%";
+		stUpdateDeviceReq.devicelist.push_back(stDevice);
+
+		if ( UpdateDeviceMessage(url, stUpdateDeviceReq, stUpdateDeviceResp) )
+		{
+			printf("更新设备信息成功:code=%s, msg=%s, str=%s\n",
+				stLoginResp.strCode.c_str(),
+				stLoginResp.strMessage.c_str(),
+				stLoginResp.strStr.c_str());
+		}
+		else
+		{
+			printf("更新设备信息失败!\n");
+		}
+
+		// ##########################心跳包机制##############################;
+		SATParameters::STHeartbeatReq stHeartbeatReq;
+		SATParameters::STHeartbeatResp stHeartbeatResp;
+		__if_not_exists(url)
+		{			
+			std::string url = host + "/btc_execute_se/ajaxInteractiveManage!executeHeartbeat.action";
+		}
+		__if_exists(url)
+		{
+			url = host + "/btc_execute_se/ajaxInteractiveManage!executeHeartbeat.action";
+		}
+
+		// 示例值;
+		//stDevice.strStatus = "0";
+		//stDevice.strDeviceSerial = "192.168.1.119:5555";
+
+		stHeartbeatReq.strUserName = "superAdmin";
+		stHeartbeatReq.strRunnerMac = "40:16:7e:23:10:53";
+		stHeartbeatReq.devicelist.push_back(stDevice);
+		if ( Heartbeat(url, stHeartbeatReq, stHeartbeatResp) )
+		{
+			printf("登录返回:code=%s, msg=%s, str=%s\n",
+				stHeartbeatResp.strCode.c_str(),
+				stHeartbeatResp.strMessage.c_str(),
+				stHeartbeatResp.strStr.c_str());
+
+			// 判断是否有任务获取成功;
+			if ( stHeartbeatResp.vtTask.size() )
+			{
+				// #########################################################################################
+				// 通知SAT变更任务状态;
+				SATParameters::STTask stTask = stHeartbeatResp.vtTask[0];
+				SATParameters::STNotifyJobStartReq stNotifyJobStartReq;
+				SATParameters::STNotifyJobStartResp stNotifyJobStartResp;
+
+				__if_not_exists(url)
+				{			
+					std::string url = host + "/btc_execute_se/ajaxInteractiveManage!setResult.action";
+				}
+				__if_exists(url)
+				{
+					url = host + "/btc_execute_se/ajaxInteractiveManage!setResult.action";
+				}
+
+				TCHAR szValue[36] = {0};
+				_itoa_s(stTask.nDeviceId, szValue, 10);
+				stNotifyJobStartReq.strDeviceId = szValue;
+
+				_itoa_s(stTask.nExecuteId, szValue, 10);
+				stNotifyJobStartReq.strExecuteId = szValue;
+
+				// _itoa_s(stTask.nInstanceId, szValue, 10); // 误导:应该使用id而不是nInstanceId
+				_itoa_s(stTask.Id, szValue, 10);
+				stNotifyJobStartReq.strInstanceId = szValue;					
+
+				_itoa_s(stTask.nTaskId, szValue, 10);
+				stNotifyJobStartReq.strTaskId = szValue;
+
+				stNotifyJobStartReq.strSignalImageUrl = "D:\\\\SAT\\\\Runner\\\\btc_runner_se\\\\runner\\\\output\\\\";//ODF_NPI_RT2841\\\\20191216101613370\\\\192.168.1.119_5555";
+				stNotifyJobStartReq.strSignalImageUrl.append(stTask.strTaskName+"\\\\");
+				stNotifyJobStartReq.strSignalImageUrl.append(stTask.Job.strUniqueId+"\\\\");
+				stNotifyJobStartReq.strSignalImageUrl.append(stTask.Job.strDeviceId);
+
+				for( int n = 0; n < 2; n++)
+				{						
+					// 查询任务是否已在SAT上存在;
+					if ( NotifyJobStart(url, stNotifyJobStartReq, stNotifyJobStartResp) )
+					{
+						// 更新设备为忙碌状态;
+						// 忙碌状态,此时请求Heartbeat将不会查询任务;
+						stDevice.strStatus = "2";
+						printf("NotifyJobStart 成功\n");
+					}
+					else
+					{
+						printf("NotifyJobStart 失败\n");
+					}
+				}
+
+				stDevice.strStatus = "0";
+				// #########################################################################################
+				// 开始Job;
+				SATParameters::STJobProcessReq stJobProcessReq;
+				SATParameters::STJobProcessResp stJobProcessResp;
+				__if_not_exists(url)
+				{			
+					std::string url = host + "/btc_execute_se/ajaxInteractiveManage!setResultList.action";
+				}
+				__if_exists(url)
+				{
+					url = host + "/btc_execute_se/ajaxInteractiveManage!setResultList.action";
+				}
+
+				{
+					stJobProcessReq.strResultState = "1";
+					stJobProcessReq.strCaseScene = "";
+					stJobProcessReq.strCaseStep = "0";
+					stJobProcessReq.strApkMD5 = "";
+					stJobProcessReq.strCrashTime = "";
+					// 就是Task中的ExecuteId
+					_itoa_s(stTask.nExecuteId, szValue, 10);
+					stJobProcessReq.strRunnerId = szValue;
+					stJobProcessReq.strCPUInfo = "0";
+					stJobProcessReq.strRunnedActionNameList = "";
+					stJobProcessReq.strArtificialResult = "";
+					stJobProcessReq.strArtificialModify = "";
+					stJobProcessReq.strRunnerName = "";
+					stJobProcessReq.strTaskType = "FUNCTIONALITY";
+					stJobProcessReq.strCaseRepeat = "";
+					stJobProcessReq.strApplicationGroup = "";
+					// 实例Id;
+					_itoa_s(stTask.nInstanceId, szValue, 10);
+					stJobProcessReq.strInstanceId = szValue;
+					stJobProcessReq.strCaseId = "";
+					stJobProcessReq.strProgress = "0";
+					stJobProcessReq.strReusltMessage = "任务开始";
+					stJobProcessReq.strJobRepeat = "";
+					stJobProcessReq.strScreenShot = "";
+					stJobProcessReq.strStartTime = "2019-12-16 10:16:43";
+					stJobProcessReq.strCrashNumber = "";
+					stJobProcessReq.strCaseName = "";
+					stJobProcessReq.strFailedReason = "";
+					stJobProcessReq.strImgName = "";
+					stJobProcessReq.strCaseIndex = "";
+					// 实例Id;
+					_itoa_s(stTask.nDeviceId, szValue, 10);
+					stJobProcessReq.strDeviceId = szValue;
+					stJobProcessReq.strSceneIndex = "";
+					// 实例Id;
+					_itoa_s(stTask.nTaskId, szValue, 10);
+					stJobProcessReq.strTaskId = szValue;
+					stJobProcessReq.strAnalysis = "";
+					// 设备名称:即DeviceSerial;
+					stJobProcessReq.strDevnceName = stDevice.strDeviceSerial;
+					// 固定为:TOTAL
+					stJobProcessReq.strInfoType = "TOTAL";
+					// 如果是Android设备,需要通过adb获取;
+					stJobProcessReq.strMemoryInfo = stDevice.strMemory;
+					stJobProcessReq.strEndTime = "2019-12-16 10:18:20";
+					stJobProcessReq.strRoundNumber = "1";
+					stJobProcessReq.strResultType = "0";
+					stJobProcessReq.strOperationStep = "";
+				}
+
+				// 
+				if ( ProcessJob(url, stJobProcessReq, stJobProcessResp) )
+				{
+					// 开始下载脚本;
+					__if_not_exists(url)
+					{			
+						std::string url = host + "/btc_caseManagement_se/ajaxInteractiveManage!getCaseFileListUrl.action";
+					}
+					__if_exists(url)
+					{
+						url = host + "/btc_caseManagement_se/ajaxInteractiveManage!getCaseFileListUrl.action";
+					}
+
+					SATParameters::STScriptUrlResp stScriptUrlResp;
+					std::vector<SATParameters::STCase>::iterator it = stTask.Job.vtCases.begin();
+					for ( ; it != stTask.Job.vtCases.end(); it++ )
+					{
+						if ( DownloadScript(url, it->strId, "D:\\SAT\\", stScriptUrlResp) )
+						{
+							printf("获取脚本下载地址成功:%s\n路径:%s\n", stScriptUrlResp.strURL.c_str(), stScriptUrlResp.strScripFile.c_str());
+							DWORD dwScriptId = RunPyScript(stScriptUrlResp.strScripFile.c_str(), "", "D:\\SAT\\log.txt", TRUE);
+							if ( dwScriptId != -1 )
+							{
+								while( !IsPyScriptOver(dwScriptId, TRUE) )
+									Sleep(100);
+							}
+							CleanPyScript(dwScriptId);
+						}
+						else
+						{
+							printf("获取脚本下载地址失败\n");
+						}
+					}						
+				}
+			}
+		}
+
+		Sleep(3000);
+	}
+
+	
+	system("pause");
+}