#include "stdafx.h"
#include "resource.h"
#include "XXXAgent.h"
#include <stdio.h>
#include "MainThread.h"
class CXXXAgentModule : public CAtlServiceModuleT< CXXXAgentModule, IDS_SERVICENAME >
{
public :
DECLARE_LIBID(LIBID_XXXAgentLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_XXXAGENT, "{87BB17B1-D004-4888-A761-8917116F337D}")
HRESULT InitializeSecurity() throw()
{
// TODO : 调用 CoInitializeSecurity 并为服务提供适当的
// 安全设置
// 建议 - PKT 级别的身份验证、
// RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
// 以及适当的非 NULL 安全说明符。
return S_OK;
}
};
CXXXAgentModule _AtlModule;
//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/, int nShowCmd)
{
return _AtlModule.WinMain(nShowCmd);
}
经过查阅资料后发现,在VS2005中,只需要重载PreMessageLoop和PostMessageLoop即可,PostMessageLoop函数里可以完成服务退出时的资源清理工作,PreMessageLoop函数里可以启动自己的线程来完成服务工作,也就是直接将以前在Run函数里所做的工作一样直接复制到这里即可. 新的框架如下:
#include "stdafx.h"
#include "resource.h"
#include "XXXAgent.h"
#include <stdio.h>
#include "MainThread.h"
class CXXXAgentModule : public CAtlServiceModuleT< CXXXAgentModule, IDS_SERVICENAME >
{
public :
DECLARE_LIBID(LIBID_XXXAgentLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_XXXAGENT, "{87BB17B1-D004-4888-A761-8917116F337D}")
HRESULT InitializeSecurity() throw()
{
// TODO : 调用 CoInitializeSecurity 并为服务提供适当的
// 安全设置
// 建议 - PKT 级别的身份验证、
// RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
// 以及适当的非 NULL 安全说明符。
return S_OK;
}
HRESULT CXXXAgentModule::PreMessageLoop(int nShowCmd) throw()
{
HRESULT hr = __super::PreMessageLoop(nShowCmd);
if (SUCCEEDED(hr) && !m_bDelayShutdown)
hr = CoResumeClassObjects();
if (SUCCEEDED(hr))
{
//开始初始化并启动服务器主线程
CMainThread MainThr;
if(!MainThr.Init())
{
LogEvent(_T("UpdateServer Service OnInit() error."));
::MessageBox(NULL, _T("服务器初始化失败.../r/n"), _T("系统错误"), MB_OK+MB_ICONSTOP);
RevokeClassObjects();
return S_FALSE;
}
if(!MainThr.Run())
{
LogEvent(_T("UpdateServer Service OnRun() error."));
::MessageBox(NULL, _T("服务器启动失败.../r/n"), _T("系统错误"), MB_OK+MB_ICONSTOP);
RevokeClassObjects();
return S_FALSE;
}
}
return hr;
}
HRESULT CXXXAgentModule::PostMessageLoop() throw()
{
HRESULT hr = __super::PostMessageLoop();
if (SUCCEEDED(hr))
{
// Add any custom code to uninitialize your service
}
return hr;
}
};
CXXXAgentModule _AtlModule;
//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/, int nShowCmd)
{
return _AtlModule.WinMain(nShowCmd);
}
那么如何重新设置服务的名称和描述信息呢,可以通过重载RegisterAppId函数来实现,具体如下:
HRESULT RegisterAppId(bool bService = false) throw()
{
HRESULT hr = S_OK;
BOOL res = __super::RegisterAppId(bService);
if (bService)
{
if (IsInstalled())
{
SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SERVICE_CHANGE_CONFIG);
SC_HANDLE hService = NULL;
if (hSCM == NULL)
hr = AtlHresultFromLastError();
else
{
hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);
if (hService != NULL)
{
TCHAR szDisplayName[128];
ZeroMemory(szDisplayName, 128);
lstrcpy(szDisplayName, _T("XXX代理服务器"));
::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, NULL, NULL, NULL, NULL, NULL, NULL, NULL, szDisplayName);
SERVICE_DESCRIPTION Description;
TCHAR szDescription[1024];
ZeroMemory(szDescription, 1024);
ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION));
lstrcpy(szDescription, _T("XXX软件有限公司 版权所有(R) 2001-2008"));
Description.lpDescription = szDescription;
::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &Description);
::CloseServiceHandle(hService);
}
else
hr = AtlHresultFromLastError();
::CloseServiceHandle(hSCM);
}
}
}
return hr;
}