如何创建一个Service
2014-07-14 18:42
288 查看
这边文章简单的向大家介绍一下如何用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内代码,就完成了。
我用的是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); }
相关文章推荐
- 如何在Mac OS X上创建一个Service服务进程
- Kivy A to Z -- 如何从Python创建一个基于Binder的Service及如何从Java访问Python创建的Service
- 如何创建一个AJAX-Enabled WCF Service
- 如何创建一个AJAX-Enabled WCF Service
- 如何使用C# WEBSERVICE 创建一个三层的数据库应用程序 http://www.xxju.net/article/200412/29_0004326567.htm
- 如何创建一个不死的Service---双进程守护
- 如何创建一个RESTful WCF Service
- 如何创建一个Android Native Binder Service
- 如何为windows2000创建一个tftp service
- 如何创建一个RESTful WCF Service
- 如何在VC中利用系统函数创建一个新的线程
- [转]Creating Custom Web Controls in C# Stats(演示了如何创建一个导航条)
- 如何用VB.Net创建一个三层的数据库应用程序
- 如何创建一个自定义帐户来运行 ASP.NET
- 如何创建一个用弹出窗口来查看详细信息的超链接列
- SQL 2K中在一个表创建好以后如何改变identity seed和identity increment??
- 如何动态创建一个按纽 并给这个按纽绑上一个Onclick事件
- 如何用Delphi创建一个能随意拨号,并连接到对方的“猫”上的程序,谢谢(小弟才浅,请指教)
- 创建一个Windows Service应用程序
- 如何创建一个用弹出窗口来查看详细信息的超链接列