vs2010下编写windows服务程序

本程序主要实现功能是通过服务开启一个界面程序和执行一些cmd命令

第一步:创建一个ATL project,选择Service(exe),创建好后我个人添加的类的声明和定义都在一个cpp里,所以下面直接上cpp代码

// ATLdemo.cpp : Implementation of WinMain


#include "stdafx.h"
#include "resource.h"
#include "ATLdemo_i.h"
#include 
#include 
#pragma comment(lib, "userenv.lib")
#include//win32 api
#pragma comment(lib, "WtsApi32.lib")
#include 
#include //shellsexcute
#pragma comment(lib, "shell32.lib")
#include "atlbase.h"
#include "fstream"
#include "iostream"
using namespace ATL;
class CATLdemoModule : public ATL::CAtlServiceModuleT< CATLdemoModule, IDS_SERVICENAME >
	{
public :
	DECLARE_LIBID(LIBID_ATLdemoLib)
	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_ATLDEMO, "{BA3C0E26-048E-464F-86FB-133DF8638B79}")
		HRESULT InitializeSecurity() throw()
	{
		// TODO : Call CoInitializeSecurity and provide the appropriate security settings for your service
		// Suggested - PKT Level Authentication, 
		// Impersonation Level of RPC_C_IMP_LEVEL_IDENTIFY 
		// and an appropiate Non NULL Security Descriptor.

		return S_OK;
	}
	void OnPause() throw(); //暂停  
    void OnStop() throw();//停止  
    void Handler(DWORD dwOpcode) throw();//处理不同的服务控制消息  
    void OnContinue() throw();//继续运行  
    HRESULT PreMessageLoop(int nShowCmd) throw();//消息响应 
	bool QuerySerStatu();//查询服务状态
	void CreateCmd();
    inline HRESULT RegisterAppId(_In_ bool bService = false) throw()//为了运行重写的 install
    {
        if (!Uninstall())
            return E_FAIL;

        CATLdemoModule::UpdateRegistryAppId(TRUE);

        CRegKey keyAppID;
        keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);

        CRegKey key;

        key.Create(keyAppID, CATLdemoModule::GetAppIdT());

        key.DeleteValue(_T("LocalService"));

        key.SetStringValue(_T("LocalService"), m_szServiceName);

        // Create service
        if (!Install())
            return E_FAIL;
        return S_OK;
    } 
	bool LaunchSession1Process( LPTSTR lpCommand );
	void RunMessageLoop() throw();
	HRESULT Run(int nShowCmd = SW_HIDE) throw();//重写run
	BOOL Install() throw();//为了重写createservice
	bool ParseCommandLine(
		_In_z_ LPCTSTR lpCmdLine,
		_Out_ HRESULT* pnRetCode) throw();
	private:
	WCHAR lpszClientPath[MAX_PATH];//当前服务路径
    _TCHAR dependServices[256];//依赖项
    DWORD size;
    DWORD dwStartType;
	//int Get_Time();
	int Share_Memory();
	bool Count_Time();
	typedef struct _Date
	{
		int i_year;
		int i_month;
		int i_day;
	}Date;
	Date Initia_time;
	Date Pay_time;
	static  int YearCalcArray[20] ;
    static int MonthCalcArray[12] ;
};
    int YearCalcArray[4] = {365, 365, 365, 366};
	int MonthCalcArray[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30,31,30,31};

CATLdemoModule _AtlModule;



//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
								LPTSTR /*lpCmdLine*/, int nShowCmd)
{

	 _AtlModule.WinMain(nShowCmd);
}
void CATLdemoModule::RunMessageLoop()throw()
{
	//to do something
			MSG msg;
		if(LaunchSession1Process(L"ll"))
           LogEvent(L"交互成功");	
		//Share_Memory();
		CreateCmd();
		if(!QuerySerStatu())
			LogEvent(L"查询状态失败");
		while (GetMessage(&msg, 0, 0, 0) > 0)
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
}
bool CATLdemoModule::LaunchSession1Process( LPTSTR lpCommand)
{
	BOOL bSuccess = FALSE;
	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi = {0};
	si.cb = sizeof(si);

	DWORD dwSessionID = WTSGetActiveConsoleSessionId();

	HANDLE hToken = NULL;
	if (WTSQueryUserToken(dwSessionID, &hToken) == FALSE)
	{
		 LogEvent(L"读取当前登录用户的令牌信息失败");
	}
	HANDLE hDuplicatedToken = NULL;
	if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDuplicatedToken) == FALSE)
	{
	    LogEvent(L"复制当前登录用户的令牌信息失败");
	}
	LPVOID lpEnvironment = NULL;
	if (CreateEnvironmentBlock(&lpEnvironment, hDuplicatedToken, FALSE) == FALSE)
	{
	    LogEvent(L"创造环境失败");
	}
	
	if (GetModuleFileName(NULL, lpszClientPath, MAX_PATH) == 0)
	{
	    LogEvent(L"获取当前进程已加载模块的文件的完整路径失败");
	}
	PathRemoveFileSpec(lpszClientPath);//删除最后文件名
	WCHAR *path=(L"C:\\windows\\system32\\cmd.exe");
	//执行cmd命令
	if (CreateProcessAsUser(hDuplicatedToken,path, NULL, NULL, NULL, FALSE,
	NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
	lpEnvironment, NULL, &si, &pi) == FALSE)
	{
		DWORD a=GetLastError();
		TCHAR str[100];
        wsprintf(str,L"%u",a);
		LogEvent((LPCTSTR)str);
	    LogEvent(L"创建新进程失败");
	}
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	bSuccess = TRUE;
	return bSuccess;
}
bool CATLdemoModule::ParseCommandLine(
		_In_z_ LPCTSTR lpCmdLine,
		_Out_ HRESULT* pnRetCode) throw()
	{
		if (!CAtlExeModuleT::ParseCommandLine(lpCmdLine, pnRetCode))
			return false;

		TCHAR szTokens[] = _T("-/");
		*pnRetCode = S_OK;

		CATLdemoModule* pT = static_cast(this);
		LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
		while (lpszToken != NULL)
		{
			if (WordCmpI(lpszToken, _T("Service"))==0)
			{
				*pnRetCode = this->RegisterAppId(true);
				if (SUCCEEDED(*pnRetCode))
					{
					*pnRetCode = this->RegisterServer(TRUE);
				}
				return false;
			}
			lpszToken = FindOneOf(lpszToken, szTokens);
		}
		return true;
	}
HRESULT CATLdemoModule::Run(int nShowCmd) throw()
	{
		HRESULT hr = S_OK;
		CATLdemoModule *pT = this;
		hr = pT->PreMessageLoop(nShowCmd);

		// Call RunMessageLoop only if PreMessageLoop returns S_OK.
		if (GetModuleFileName(NULL, lpszClientPath, MAX_PATH) == 0)
		{
			LogEvent(L"获取当前进程已加载模块的文件的完整路径失败");
		}
	    PathRemoveFileSpec(lpszClientPath);//删除最后文件名
		wcscat_s(lpszClientPath, sizeof(lpszClientPath)/sizeof(WCHAR), L"time_rec.txt");
		//SYSTEMTIME sys;//获取系统时间
		fstream file;
		file.open();
		//while(1){
		//GetLocalTime( &sys );   
		//int Time_Year=sys.wYear;
		//int Time_second=sys.wSecond;
		//int Time_Minute=sys.wMinute;
		//wchar_t ch[20];
		_stprintf_s(ch,"%d",Time_Minute);
		//_itow_s(Time_second, ch, 20, 10);
		//LPWSTR tittle=L"hello";
		//DWORD resp;
		//WTSSendMessage(
		//	WTS_CURRENT_SERVER_HANDLE, 
		//	WTSGetActiveConsoleSessionId(),
		//	tittle,5,
		//	ch,20, 
		//	0, 0, &resp,false);
		//Sleep(5000);
		//}
		if (hr == S_OK)
		{
			pT->RunMessageLoop();
		}

		// Call PostMessageLoop if PreMessageLoop returns success.
		if (SUCCEEDED(hr))
		{
			hr = pT->PostMessageLoop();
		}

		ATLASSERT(SUCCEEDED(hr));

		return hr;
	}
HRESULT CATLdemoModule::PreMessageLoop( int nShowCmd ) throw()  
{  
   //让服务允许暂停和继续操作  
   m_status.dwControlsAccepted = m_status.dwControlsAccepted|SERVICE_ACCEPT_PAUSE_CONTINUE;  
   HRESULT hr = __super::PreMessageLoop(nShowCmd);  
   if (hr == S_FALSE)  
   {  
       hr = S_OK;
   }  
  
   //将服务状态设置为启动  
   SetServiceStatus(SERVICE_RUNNING);  
  
   //写入系统日志  
   LogEvent(L"ATLDemo Service Start Successfully~!"); 
     HANDLE hToken;  
    TOKEN_PRIVILEGES tkp;  
	bool ret;
    ret=OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	if(!ret)
		LogEvent(L"获取令牌句柄失败!!"); 
	LUID Luid;
	ret= LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME ,&Luid);
	if(!ret)
		LogEvent(L"获取Luid失败"); 
	tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
	tkp.Privileges[0].Luid=Luid;
    //AdjustTokenPrivileges(hToken, FALSE, &tkp,sizeof(TOKEN_PRIVILEGES),NULL, NULL); 
	   AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 
        (PTOKEN_PRIVILEGES)NULL, 0); 
	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
	{
		LogEvent(L"修改特权失败");
	}
	 if(GetLastError()== ERROR_SUCCESS)  //修改权限成功
	 {
		 LogEvent(L"修改特权成功"); 
		 //ShellExecute(NULL, L"Open", L"C:\\Users\\Administrator\\Desktop\\NCG00.txt", NULL, NULL, SW_SHOWNORMAL);
	 }
   return hr;  
}  
void CATLdemoModule::Handler( DWORD dwOpcode ) throw()  
{  
    switch(dwOpcode)  
    {  
    case SERVICE_CONTROL_PAUSE://暂停  
        {  
            OnPause();  
            break;  
        }  
    case SERVICE_CONTROL_CONTINUE://继续  
        {  
            OnContinue();  
            break;  
        }  
    default:  
        break;  
    }  
  
    __super::Handler(dwOpcode);  
}  
void CATLdemoModule::OnPause() throw()  
{  
    //设置服务状态为暂停  
    SetServiceStatus(SERVICE_PAUSED);  
  
    __super::OnPause();  
}  
void CATLdemoModule::OnStop() throw()  
{  
     //设置服务状态为停止  
    SetServiceStatus(SERVICE_STOPPED);  
  
    __super::OnStop();  
}   
void CATLdemoModule::OnContinue() throw()  
{  
    //设置服务状态为启动  
    SetServiceStatus(SERVICE_RUNNING);  
  
     __super::OnContinue();  
}  
BOOL CATLdemoModule::Install() throw()
	{
		if (IsInstalled())
			return TRUE;
		
		// Get the executable file path
		TCHAR szFilePath[MAX_PATH + _ATL_QUOTES_SPACE];
		DWORD dwFLen = ::GetModuleFileName(NULL, szFilePath + 1, MAX_PATH);
		if( dwFLen == 0 || dwFLen == MAX_PATH )
			return FALSE;

		// Quote the FilePath before calling CreateService
		szFilePath[0] = _T('\"');
		szFilePath[dwFLen + 1] = _T('\"');
		szFilePath[dwFLen + 2] = 0;

		SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
		if (hSCM == NULL){
			LogEvent(L"打开SCM失败");
		}
		//创建服务
		LogEvent(L"进入Install");
		SC_HANDLE hService = ::CreateService(        
			hSCM, L"supsys",L"Support System",
			SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
			SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
			szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);
		    if (hService == NULL)
			{
				DWORD error=GetLastError();
				//LogEvent((LPCTSTR)error);
				::CloseServiceHandle(hSCM);
				LogEvent(L"CreateService failure");
				return FALSE;
			}
			LogEvent(L"CreateService successful");
			///
	 		hSCM = ::OpenSCManager(NULL,NULL,SERVICE_CHANGE_CONFIG);
			hService=::OpenService(hSCM,L"supsys",SERVICE_CHANGE_CONFIG);
			if(hService==NULL)
				LogEvent(L"123");
                    SERVICE_DESCRIPTION sDescription;  
                    TCHAR szDescription[1024];  
                    ZeroMemory(szDescription,1024);  
                    ZeroMemory(&sDescription,sizeof(SERVICE_DESCRIPTION));  
  
                    //服务描述  
                    lstrcpy(szDescription,L"windows服务支持!");  
                    sDescription.lpDescription = szDescription;  
  
                    //修改服务描述信息  
                    ChangeServiceConfig2(hService,SERVICE_CONFIG_DESCRIPTION,&sDescription); 
					::CloseServiceHandle(hService);
		            ::CloseServiceHandle(hSCM);
	 
		return TRUE;
	}
bool CATLdemoModule::Count_Time()
{
		SYSTEMTIME sys;//获取系统时间
		GetLocalTime( &sys ); 
		Date Current_Time;
		Current_Time.i_year=sys.wYear;
		Current_Time.i_month=sys.wMonth;
		Current_Time.i_day=sys.wDay;
		while(1){
		int i=Pay_time.i_day-Current_Time.i_day;
		if(i>=0&&i<3)
			{//show the warning;
		}
		else if(i<0)
			{//kill the process;
		}
		}
}
//共享内存获得变量
int CATLdemoModule::Share_Memory()
{
	int nRetCode = 0;
	while(1){
    HANDLE hMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS,NULL,L"Global\\ShareMemory");
    if (hMapping)
    {
        LogEvent(L"Success Share_Memory");
        LPVOID lpBase = MapViewOfFile(hMapping,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
        char szBuffer[5] = {0};
        strcpy(szBuffer,(char*)lpBase);
		if(!strcmp(szBuffer,"true")){
        LogEvent(L"true");
		}
        UnmapViewOfFile(lpBase);
        CloseHandle(hMapping);
		nRetCode=1;
		OnStop();
		break;
    }
    else
    {
        LogEvent(L"OpenMapping Error");
    }
	}
    return nRetCode;
}
bool CATLdemoModule::QuerySerStatu(){
	SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);//打开SCmanager
	if (!schSCManager)//打开失败
	{
		LogEvent(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
		return false;
	}
	LPCTSTR MySer_Name=L"ZhuDongFangYu";
	SC_HANDLE schService = OpenService(schSCManager, MySer_Name, //打开服务
	SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
	if (NULL != schService)//服务存在
	{
		LogEvent(L"主动防御 was installed.\n");
		DWORD cbBytesNeeded;

		// 
		// Query the status of the service
		// 

		SERVICE_STATUS_PROCESS ssp;
		if (QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, 
			sizeof(ssp), &cbBytesNeeded))
		{
			LogEvent(L"Service status: ");
			if(ssp.dwCurrentState==SERVICE_RUNNING)//正在运行返回true
			{
				::CloseServiceHandle(schSCManager);
				::CloseServiceHandle(schService);
			    return true;
			}
			else
			{
				::CloseServiceHandle(schSCManager);
				::CloseServiceHandle(schService);
				return false;
			}
			//switch (ssp.dwCurrentState)
			//{
			//case SERVICE_STOPPED: _putws(L"Stopped"); break;
			//case SERVICE_RUNNING: _putws(L"Running"); break;
			//case SERVICE_PAUSED: _putws(L"Paused"); break;
			//case SERVICE_START_PENDING:
			//case SERVICE_STOP_PENDING:
			//case SERVICE_CONTINUE_PENDING:
			//case SERVICE_PAUSE_PENDING: _putws(L"Pending"); break;
			//}
		}
		else
		{
			LogEvent(L"QueryServiceStatusEx failed w/err 0x%08lx\n", GetLastError());
		}
		
			::CloseServiceHandle(schSCManager);
			::CloseServiceHandle(schService);
	}
	else//服务不存在返回flase
	{
		LogEvent(L"主动防御 was unstalled.\n");
		::CloseServiceHandle(schSCManager);
		::CloseServiceHandle(schService);
		return false;
		
	}
}
void CATLdemoModule::CreateCmd(){

	
}
以上可以说实现了一个最基本的服务程序,服务程序不能直接debug,要先生成(注意生成时如果这个服务正在运行或已经注册将会失败)

让服务注册运行的cmd命令为

d:
cd D:\work project\me\daima\ATLdemo\Debug
atldemo.exe /service
net start supsys

删除服务的命令为

atldemo /unregserver


sc delete atldemo

你可能感兴趣的:(windows服务,windows系统)