******CNTServices.h******
/*有错误*/
#include <windows.h>
#include <stdio.h>
class CNTServices
{
public:
SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
/***************************************************************
*static function
*/
// Control Handler
static void WINAPI ControlHandler(DWORD request);
//Service main program
static void WINAPI ServiceMain(int argc, char** argv);
/*
static member
*/
static CNTServices* m_pThis; // nasty hack to get object ptr
public:
char m_szServicename[MAX_PATH];
char m_szFilePath[MAX_PATH];
CNTServices(char* szServiceName);
virtual ~CNTServices()
{
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
}
//获取当前程序路径,不包含程序名
void GetAppPath()
{
char szExePath[MAX_PATH] = { 0 };
GetModuleFileName(NULL, szExePath, MAX_PATH);
strncpy(m_szFilePath, szExePath, strlen(szExePath)-strlen("KillProcess.exe"));
}
//写日志
int WriteToLog(char* str)
{
FILE* log;
char szLogPath[MAX_PATH] = { 0 };
sprintf(szLogPath, "%slog.txt", m_szFilePath);
log = fopen(szLogPath, "a+");
if (log == NULL)
{
OutputDebugString("Log file open failed.");
return -1;
}
//write str in logfile
SYSTEMTIME systemTime;
/* ::GetSystemTime(&systemTime); //返回值中小时总是比系统时间少八个小时
//这是世界标准时间。和我国的时间不一样
//getlocaltime 返回的才是本地时间
*/
::GetLocalTime(&systemTime);
char sztime[MAX_PATH] = {0};
sprintf(sztime, "%d-%d-%d %d:%d:%d", systemTime.wYear, systemTime.wMonth, systemTime.wDay,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
char szlog[MAX_PATH] = {0};
sprintf(szlog, "%s /t%s", sztime, str);
fprintf(log, "%s/n", szlog);
fclose(log);
return 0;
}
int InitService()
{
OutputDebugString("Monitoring started.");
int result;
result = WriteToLog("Monitoring started.");
return(result);
}
virtual void DoTask() = 0;
};
********CNTServices.cpp***********
#include "CNTServices.h"
// static variables
CNTServices* CNTServices::m_pThis = NULL;
CNTServices::CNTServices(char* szServiceName)
{
memset(m_szServicename, 0, MAX_PATH);
memset(m_szFilePath, 0, MAX_PATH);
strcpy(m_szServicename, szServiceName);
GetAppPath();
m_pThis = this;
}
void CNTServices::ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
OutputDebugString("Monitoring stopped.");
m_pThis->WriteToLog("Monitoring stopped.");
m_pThis->m_ServiceStatus.dwWin32ExitCode = 0;
m_pThis->m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (m_pThis->m_ServiceStatusHandle, &m_pThis->m_ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
OutputDebugString("Monitoring stopped.");
m_pThis->WriteToLog("Monitoring stopped.");
m_pThis->m_ServiceStatus.dwWin32ExitCode = 0;
m_pThis->m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (m_pThis->m_ServiceStatusHandle, &m_pThis->m_ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (m_pThis->m_ServiceStatusHandle, &m_pThis->m_ServiceStatus);
return;
}
void CNTServices::ServiceMain(int argc, char** argv)
{
int error;
m_pThis->m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_pThis->m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_pThis->m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
m_pThis->m_ServiceStatus.dwWin32ExitCode = 0;
m_pThis->m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_pThis->m_ServiceStatus.dwCheckPoint = 0;
m_pThis->m_ServiceStatus.dwWaitHint = 0;
m_pThis->m_ServiceStatusHandle = RegisterServiceCtrlHandler(
m_pThis->m_szServicename/*"MemoryStatus"*/,
ControlHandler/*(LPHANDLER_FUNCTION)ControlHandler*/);
//error reason:ControlHandler属于这个类,而LPHANDLER_FUNCTION不属于这个类
//so: ControlHandler应该改为静态函数
if (m_pThis->m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
// Initialize Service ,InitService()是自己的代码
error = m_pThis->InitService();
if (error)
{
// Initialization failed
m_pThis->m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_pThis->m_ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(m_pThis->m_ServiceStatusHandle, &m_pThis->m_ServiceStatus);
return;
}
// We report the running status to SCM.
m_pThis->m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (m_pThis->m_ServiceStatusHandle, &m_pThis->m_ServiceStatus);
// The worker loop of a service
while (m_pThis->m_ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
m_pThis->DoTask();
}
return;
}
*********KillProcess.h***********
#include "CNTServices.h"
class CKillProcess : public CNTServices
{
struct PROCINFO
{
char szName[26];
int nLivingTime; //被杀进程允许存活时间
int nLeaveTime;
HANDLE hProcess;
DWORD dwProcessId[2]; //检测到的被杀进程ID
int i;
};
PROCINFO* m_pProc;
char m_szTimeUnit[7]; //3个值:"minute", "hour", "second"
int m_nCheckTime; //程序检测时间
int m_nProcessNum;
bool m_bIfIniRight;
public:
CKillProcess(char* szName) : CNTServices(szName)
{
// m_nProcessNum = 1;
// m_nCheckTime = 1;
m_pProc = 0;
m_bIfIniRight = true;
memset(m_szTimeUnit, 0, 7);
strcpy(m_szTimeUnit, "second");
ReadIniFile();
}
~CKillProcess()
{
if(m_pProc != NULL)
{
delete [] m_pProc;
m_pProc = NULL;
}
}
int TransTime(const char* szTimeUnit, int nTranTime)
{
//因为Sleep参数是毫秒,*1000=秒
if(strcmp(szTimeUnit, "minute") == 0)
{
// m_nCheckTime = atoi(szChecktime)*1000*60;//单位是分钟
// m_nLivingTime = atoi(szLivingtime)*1000*60;
WriteToLog("time_unit is minute!");
return nTranTime*1000*60;
}
else if(strcmp(szTimeUnit, "hour") == 0)
{
// m_nCheckTime = atoi(szChecktime)*1000*60*60;//单位是小时
// m_nLivingTime = atoi(szLivingtime)*1000*60*60;
WriteToLog("time_unit is hour!");
return (nTranTime*1000*60*60);
}
else if(strcmp(szTimeUnit, "second") == 0)
{
WriteToLog("time_unit is second!");
return nTranTime*1000;
}
else
{
WriteToLog("time_unit setting error!");
return -1;
}
}
void InitProcInfo(int nProcessNum, char* szIniFile)
{
/// PROCINFO proc[nProcessNum];
m_pProc = new PROCINFO[nProcessNum];
int j;
for(j = 0; j < nProcessNum; j++)
{
char szProcName[26] = {0};
int nLivingtime = 0;
char szArea[26] = {0};
sprintf(szArea, "process_%d", j);
int value2;
value2 = ::GetPrivateProfileString(szArea, "PROCESS_NAME", NULL, szProcName, 26, szIniFile);
nLivingtime = GetPrivateProfileInt(szArea, "LIVING_TIME", -1, szIniFile);
if(value2 == 0 || nLivingtime == 0)
{
char strtmp[80] = {0};
sprintf(strtmp, "can't find right set: process_%d or process_name or living_time", j);
WriteToLog(strtmp);
m_bIfIniRight = false;
return ;
}
if(strcmp(szProcName,"") == 0)
{
WriteToLog("error: process_name set null!");
m_bIfIniRight = false;
return ;
}
// m_pProc[j].szName = szProcName;//error
memset(m_pProc[j].szName, 0, 26);
strcpy(m_pProc[j].szName, szProcName);
int time = TransTime(m_szTimeUnit, nLivingtime);
if(time == -1)
{
WriteToLog("error: living_time setting!");
m_bIfIniRight = false;
return ;
}
m_pProc[j].nLivingTime = m_pProc[j].nLeaveTime = time;
m_pProc[j].dwProcessId[0] = m_pProc[j].dwProcessId[1] = 0;
m_pProc[j].hProcess = 0;
m_pProc[j].i = 0;
}
}
void CreateIniFile(char* szIniFile)
{
//怎样在配置文件中写入空行??????
WritePrivateProfileString("SETTING", "TIME_UNIT", "second", szIniFile);
WritePrivateProfileString("SETTING", "CHECK_TIME", "1", szIniFile);
WritePrivateProfileString("SETTING", "PROCESS_NUM", "1", szIniFile);
// WritePrivateProfileString("", "", "", szIniFile);
WritePrivateProfileString("PROCESS_0", "PROCESS_NAME", "***", szIniFile);
WritePrivateProfileString("PROCESS_0", "LIVING_TIME", "1", szIniFile);
}
void ReadIniFile()
{
//get base setting param
char szIniFile[MAX_PATH] = {0};
sprintf(szIniFile, "%sKillProcess.ini", CNTServices::m_szFilePath);
FILE* pFini = fopen(szIniFile, "r");//判断是否有配置文件
if(pFini == NULL)
{
CreateIniFile(szIniFile);
m_nProcessNum = 1;
}
else
{
fclose(pFini);
pFini = NULL;
int value1;
char szProcessNum[3] = {0};
/// char szCheckUnit[7] = {0};
int nChecktime = 0;
value1 = ::GetPrivateProfileString("setting", "TIME_UNIT ", NULL, m_szTimeUnit, 7, szIniFile);
// value2 = ::GetPrivateProfileInt("SETTING", "PROCESS_NUM", m_nProcessNum, szIniFile);//用法错误
m_nProcessNum = ::GetPrivateProfileInt("SETTING", "PROCESS_NUM", -1, szIniFile);
// m_nProcessNum = atoi(szProcessNum);
if(m_nProcessNum == -1)
{
// m_nProcessNum = 1;
WriteToLog("error:process_num setting");
m_bIfIniRight = false;
return ;
}
nChecktime = GetPrivateProfileInt("setting", "check_time", nChecktime, szIniFile);
/* *
*测试代码
*
char strtmp[4] = {0};
sprintf(strtmp, "%d", value);
WriteToLog(strtmp);*/
//GetPrivateProfileString没有找到正确的setting或check_time
if(0 == value1 || 0 == m_nProcessNum || 0 == nChecktime)
{
WriteToLog("can't find right set: setting or time_unit or check_time or process_num");
m_bIfIniRight = false;
return ;
}
else
{
m_nCheckTime = TransTime(m_szTimeUnit, nChecktime);
if(m_nCheckTime == -1)
{
WriteToLog("error:check_time or time_unit setting");
m_bIfIniRight = false;
return ;
}
}
}
InitProcInfo(m_nProcessNum, szIniFile);
}
bool FindProcessByName();
void KillProcess(int nProcNo);
void DoTask();
};
********KillProcess.cpp**********
#include "KillProcess.h"
#include <windows.h>
#include <Tlhelp32.h>
bool CKillProcess::FindProcessByName()
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(INVALID_HANDLE_VALUE == hSnapshot)
{
CNTServices::WriteToLog("CreateToolhelp32Snapshot fail!");
::CloseHandle(hSnapshot);
return false;
}
PROCESSENTRY32 prosinfo;
prosinfo.dwSize = sizeof(prosinfo);
bool bState = Process32First(hSnapshot, &prosinfo);
if(!bState)
{
CNTServices::WriteToLog("Process32First fail!");
::CloseHandle(hSnapshot);
return false;
}
while(bState)
{
char* pStr = prosinfo.szExeFile;
int j;
for(j = 0; j < m_nProcessNum; j++)
{
//找到进程
if(strcmp(pStr, m_pProc[j].szName) == 0)
{
m_pProc[j].dwProcessId[m_pProc[j].i] = prosinfo.th32ProcessID;
//对于同样的进程,每次OpenProcess返回的handle都不一样
m_pProc[j].hProcess = ::OpenProcess(PROCESS_TERMINATE, false, m_pProc[j].dwProcessId[m_pProc[j].i]);
if(NULL == m_pProc[j].hProcess)
{
CNTServices::WriteToLog("OpenProcess failed!");
::CloseHandle(hSnapshot);
return false;
}
m_pProc[j].i = (m_pProc[j].i + 1) % 2;
::CloseHandle(hSnapshot);
return true;
}
}
bState = Process32Next(hSnapshot, &prosinfo);
}
::CloseHandle(hSnapshot);
return false;
}
void CKillProcess::KillProcess(int nProcNo)
{
bool bResult = ::TerminateProcess(m_pProc[nProcNo].hProcess, 0);
if(!bResult)
{
CNTServices::WriteToLog("TerminateProcess failed!");
}
else
CNTServices::WriteToLog("TerminateProcess success!");
}
void CKillProcess::DoTask()
{
if(!m_bIfIniRight)
{
WriteToLog("monitor haven't run!/tplease set again!");
Sleep(1000*60*10);
return ;
}
int j;
if(FindProcessByName())//find process for killed
{
/* //对于同样的进程,每次打开得到的句柄是不一样的,如果仅仅在KillProcess中关闭
//一个的话,那么就会多出一句柄来,而当不在KillProcess中关闭的话,也会多出一个来
if(m_dwProcessId[0] == m_dwProcessId[1])
{
m_nLeaveTime = m_nLeaveTime - m_nCheckTime;
if(m_nLeaveTime <= m_nCheckTime)
KillProcess();
}
::CloseHandle(m_hProcess);//注意要在此处去释放句柄*/
for(j = 0; j < m_nProcessNum; j++)
{
if(m_pProc[j].dwProcessId[0] == m_pProc[j].dwProcessId[1])
{
m_pProc[j].nLeaveTime -= m_nCheckTime;
if(m_pProc[j].nLeaveTime <= m_nCheckTime)
{
KillProcess(j);
m_pProc[j].nLeaveTime = m_pProc[j].nLivingTime;
}
}
if(m_pProc[j].hProcess != 0)
::CloseHandle(m_pProc[j].hProcess);
}
}
else
{
for(j = 0; j < m_nProcessNum; j++)
m_pProc[j].dwProcessId[0] = m_pProc[j].dwProcessId[1] = 0;
}
Sleep(m_nCheckTime);
}
int main()
{
CNTServices* pService;
pService = new CKillProcess("MonitorDebug");
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = pService->m_szServicename;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)pService->ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
delete pService;//删除时会出错,为什么??????,因为析构函数不是虚函数,继承时出现问题
return 0;
}