如何创建一个Service

这边文章简单的向大家介绍一下如何用ATL 创建一个Service。

我用的是Visual studio 2010。


首先从VS2010中选择File -> New -> Project... 。选择Visual C++ -> ATL -> ATL Project。

写好Name,点击OK。再点击Next。然后选择Service(EXE),点击Finish。

这时你会发现一个空的Service就已经被创建了。然后里面只有两个函数。_tWinMain 和InitializeSecurity

明显只有这两个函数是不够的。因此还须添加其他一些函数。具体请看以下全部CPP内的代码。只需更改CPP内代码,就完成了。

// TestService.cpp : Implementation of WinMain


#include <stdio.h>
#include "stdafx.h"
#include "resource.h"
#include "TestService_i.h"


#define SERVICE_NAME  _T("Test Service")
#define SERVICE_DESC  _T("Test Service")

const TCHAR REG_KEY_TESTSRV[] = _T("SYSTEM\\CurrentControlSet\\Services\\Test Service");

class CTestServiceModule : public ATL::CAtlServiceModuleT< CTestServiceModule, IDS_SERVICENAME >
	{
public :
	DECLARE_LIBID(LIBID_TestServiceLib)
	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_TESTSERVICE, "{6F4B5E0D-EBCC-472C-AD6A-897DC5BA19A1}")
		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.

		HRESULT hResult = CoInitializeSecurity(
			NULL,-1,NULL,NULL,
			RPC_C_AUTHN_LEVEL_DEFAULT,
			RPC_C_IMP_LEVEL_IMPERSONATE,
			NULL,EOAC_NONE,NULL);
		if(FAILED(hResult)){
			return FALSE;
		}


		return S_OK;
	}

		HRESULT RegisterAppId(bool bService = false) throw()
		{
			if (!Uninstall()) {
				return E_FAIL;
			}

			HRESULT hr = UpdateRegistryAppId(TRUE);
			if (FAILED(hr)) {
				return hr;
			}

			CRegKey keyAppID;
			LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
			if (lRes != ERROR_SUCCESS) {
				return AtlHresultFromWin32(lRes);
			}

			CRegKey key;
			lRes = key.Create(keyAppID, GetAppIdT());
			if (lRes != ERROR_SUCCESS) {
				return AtlHresultFromWin32(lRes);
			}

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

			if (!bService)
				return S_OK;

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

			// Create service
			if (!Install()) {
				return E_FAIL;
			}
			return S_OK;
		}

		BOOL 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)
			{
				return FALSE;
			}

			SC_HANDLE hService = ::CreateService(
				hSCM, m_szServiceName, m_szServiceName,
				SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
				SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
				szFilePath, NULL, NULL, _T("Winmgmt\0\0"), NULL, NULL);

			if (hService == NULL)
			{
				::CloseServiceHandle(hSCM);
				return FALSE;
			}

			//Service Settings
			if(!UpdateServiceSetting(hService,szFilePath))
			{
				::CloseServiceHandle(hSCM);
				return FALSE;
			}	

			::CloseServiceHandle(hService);
			::CloseServiceHandle(hSCM);
			return TRUE;
		}

		int WinMain(HINSTANCE hInstance) throw()
		{
			HRESULT hr = S_OK;

			LPTSTR lpCmdLine = GetCommandLine();
			if (ParseCommandLine(lpCmdLine, &hr) == true) {
				hr = Start(hInstance);
			}

			return hr;
		}

		HRESULT Start(HINSTANCE hInstance) throw()
		{

			CRegKey keyAppID;
			LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ);
			if (lRes != ERROR_SUCCESS)
			{
				m_status.dwWin32ExitCode = lRes;
				return m_status.dwWin32ExitCode;
			}

			CRegKey key;
			lRes = key.Open(keyAppID, GetAppIdT(), KEY_READ);
			if (lRes != ERROR_SUCCESS)
			{
				m_status.dwWin32ExitCode = lRes;
				return m_status.dwWin32ExitCode;
			}

			TCHAR szValue[MAX_PATH];
			DWORD dwLen = MAX_PATH;
			lRes = key.QueryStringValue(_T("LocalService"), szValue, &dwLen);

			m_bService = FALSE;
			if (lRes == ERROR_SUCCESS)
				m_bService = TRUE;

			if (m_bService)
			{
				SERVICE_TABLE_ENTRY st[] =
				{
					{ m_szServiceName, _ServiceMain },
					{ NULL, NULL }
				};
				if (::StartServiceCtrlDispatcher(st) == 0)
					m_status.dwWin32ExitCode = GetLastError();
				return m_status.dwWin32ExitCode;
			}

			// local server - call Run() directly, rather than
			// from ServiceMain()
			m_status.dwWin32ExitCode = Run(hInstance);
			return m_status.dwWin32ExitCode;
		}

		void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw()
		{
			lpszArgv;
			dwArgc;
			// Register the control request handler
			m_status.dwCurrentState = SERVICE_START_PENDING;
			m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
			m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
			if (m_hServiceStatus == NULL)
			{
				//LogEvent(_T("Handler not installed"));
				return;
			}
			SetServiceStatus(SERVICE_START_PENDING);

			m_status.dwWin32ExitCode = S_OK;
			m_status.dwCheckPoint = 0;
			m_status.dwWaitHint = 0;

#ifndef _ATL_NO_COM_SUPPORT

			HRESULT hr = E_FAIL;
			hr = InitializeCom();
			if (FAILED(hr))
			{
				// Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing
				// COM and InitializeCOM trying to initialize COM with different flags.
				if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL)
				{
					return;
				}
			}
			else
			{
				m_bComInitialized = true;
			}

			m_bDelayShutdown = false;
#endif //_ATL_NO_COM_SUPPORT
			// When the Run function returns, the service has stopped.
			m_status.dwWin32ExitCode = Run(SW_HIDE);

#ifndef _ATL_NO_COM_SUPPORT
			if (m_bService && m_bComInitialized)
				UninitializeCom();
#endif

			SetServiceStatus(SERVICE_STOPPED);
			//LogEvent(_T("Service stopped"));
		}

		HRESULT Run(HINSTANCE hInstance) throw()
		{
			HRESULT hr = S_OK;

			hr = PreMessageLoop(SW_HIDE);

			if (hr == S_OK)
			{
				if (m_bService)
				{
					//LogEvent(_T("Service started"));
					SetServiceStatus(SERVICE_RUNNING);
				}

				RunMessageLoop(hInstance);
			}

			if (SUCCEEDED(hr))
			{
				hr = PostMessageLoop();
			}

			return hr;
		}

		HRESULT PreMessageLoop(int nShowCmd) throw()
		{
			HRESULT hr = __super::PreMessageLoop(SW_HIDE);

#if _ATL_VER >= 0x0700
			if (SUCCEEDED(hr) && !m_bDelayShutdown)
				hr = CoResumeClassObjects();
#endif
			return hr;
		}

		void RunMessageLoop(HINSTANCE hInstance) throw()
		{
			MSG msg;
			while (GetMessage(&msg, 0, 0, 0) > 0)
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}

		}

		HRESULT PostMessageLoop()
		{
			return __super::PostMessageLoop();
		}

		void OnStop() throw()
		{
		
			SetServiceStatus(SERVICE_STOPPED);
			__super::OnStop();
		}

		void OnShutdown() throw()
		{

			SetServiceStatus(SERVICE_STOPPED);
			__super::OnShutdown();
		}

		BOOL UpdateServiceSetting(SC_HANDLE hService,LPCTSTR lpszFilePath)
		{
			if(!ChangeServiceConfig(
				hService,
				SERVICE_WIN32_OWN_PROCESS,
				SERVICE_AUTO_START,
				SERVICE_ERROR_NORMAL,
				lpszFilePath,
				NULL,NULL,NULL,NULL,NULL,
				SERVICE_NAME)){
					return FALSE;
			}

			CRegKey keyTestService;
			LONG lRes = keyTestService.Open(HKEY_LOCAL_MACHINE, REG_KEY_TESTSRV, KEY_WRITE);
			if (lRes != ERROR_SUCCESS){
				return FALSE;
			}
			keyTestService.SetStringValue(_T("Description"), SERVICE_DESC);
			keyTestService.Close();

			return TRUE;
		}
	};

CTestServiceModule _AtlModule;



//
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, 
								LPTSTR /*lpCmdLine*/, int /*nShowCmd*/)
{
	return _AtlModule.WinMain(hInstance);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值