之前有一篇“C++exe做系统服务,自动加载”是C语言风格的方式,使用是没有问题,但是很杂乱,这里对之封装,简化使用方式。
WindowsService.h
#pragma once
#include <string>
using namespace std;
//注入Windows服务类
class CWindowsService
{
public:
CWindowsService();//构造函数
CWindowsService(const string strServiceName);//构造函数
~CWindowsService();//析构函数
void SetServiceName(const string strServiceName);//设置服务名称(所有操作前必须调用)
void Run();//一键自助安装服务
private:
bool Install(int & dwCurrentState);//安装服务
bool Uninstall();//卸载服务
bool Start();//启动服务
bool Stop();//停止服务
static void ServiceMain(DWORD argc, LPTSTR *argv);//创建服务主要处理逻辑
static void ServiceCtrlHandler(DWORD nControlCode);//接受servicecontrol 命令
BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);//更新服务状态 更新失败即结束服务
BOOL StartServiceThread();//创建主窗口线程
static DWORD ServiceExecutionThread(LPDWORD param);//创建服务主线程
void KillService();// 停止服务 即结束主窗口线程 设置状态失败或是收到STOP SERVICE 命令调用此函数
private:
HANDLE m_hServiceThread;
SERVICE_STATUS_HANDLE m_nServiceStatusHandle;
HANDLE m_EventkillService;
HWND m_hMain;
BOOL m_bServiceRunning;
DWORD m_dwServiceCurrentStatus;
string m_ServiceDisplayName;
string m_ServiceName;
};
extern CWindowsService *g_pWindowsService;
WindowsService.cpp
#include "stdafx.h"
#include "WindowsService.h"
#include "server.h"
CWindowsService *g_pWindowsService = NULL;
//构造函数
CWindowsService::CWindowsService()
{
m_hServiceThread = 0;
m_nServiceStatusHandle = 0;
m_EventkillService = NULL;
m_hMain = NULL;
m_bServiceRunning = FALSE;
m_dwServiceCurrentStatus = 0;
}
CWindowsService::CWindowsService(const string strServiceName)
{
CWindowsService();
m_ServiceDisplayName = strServiceName;
m_ServiceName = strServiceName;
}
//析构函数
CWindowsService::~CWindowsService()
{
}
//设置服务名称
void CWindowsService::SetServiceName(const string strServiceName)
{
m_ServiceDisplayName = strServiceName;
m_ServiceName = strServiceName;
}
//一键自助安装服务
void CWindowsService::Run()
{
BOOL bNT = FALSE;
BOOL bInstalled = FALSE;
int dwCurrentState = 0;
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
if (hScm)
{
bNT = TRUE;
hService = OpenService(hScm, m_ServiceName.c_str(), GENERIC_READ);
if (hService)
{
bInstalled = TRUE;
SERVICE_STATUS ServiceStatus;
if (QueryServiceStatus(hService, &ServiceStatus))
{
dwCurrentState = ServiceStatus.dwCurrentState;
if (dwCurrentState == SERVICE_START_PENDING)
{
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
char chServiceName[256] = "";
strcpy_s(chServiceName, m_ServiceName.c_str());
const SERVICE_TABLE_ENTRY servicetable[] =
{
{ chServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL,NULL }
};
BOOL success;
success = StartServiceCtrlDispatcher(servicetable);
if (!success)
{
int nError = GetLastError();
TCHAR buffer[1000];
_stprintf_s(buffer, _T("启动服务出错,错误码:%d"), nError);
MessageBox(0, buffer, m_ServiceName.c_str(), MB_OK);
}
return ;
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hScm);
}
if (!bInstalled)
{
if (MessageBox(0, _T("是否安装服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES)
{
if (!Install(dwCurrentState))
{
MessageBox(0, _T("安装服务失败"), m_ServiceName.c_str(), MB_OK);
return;
}
}
else
return ;
}
if (dwCurrentState == SERVICE_STOPPED && (MessageBox(0, _T("启动服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES))
{
if (!Start())
{
MessageBox(0, _T("启动服务失败"), m_ServiceName.c_str(), MB_OK);
}
return;
}
if (dwCurrentState == SERVICE_STOPPED && (MessageBox(0, _T("卸载服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES))
{
if (!Uninstall())
{
MessageBox(0, _T("卸载服务失败"), m_ServiceName.c_str(), MB_OK);
}
return ;
}
if (dwCurrentState != SERVICE_STOPPED && (MessageBox(0, _T("停止服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES))
{
if (!Stop())
{
MessageBox(0, _T("停止服务失败"), m_ServiceName.c_str(), MB_OK);
}
return;
}
if (dwCurrentState == SERVICE_STOPPED)
return ;
}
//安装服务
bool CWindowsService::Install(int & dwCurrentState)
{
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if (!hScm)
{
return false;
}
int nStartMode = SERVICE_AUTO_START;
if (MessageBox(0, _T("自动运行服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES)
{
nStartMode = SERVICE_AUTO_START;
}
TCHAR buffer[MAX_PATH + 3];
buffer[0] = '"';
DWORD written = GetModuleFileName(0, buffer + 1, MAX_PATH);
if (!written)
{
CloseServiceHandle(hScm);
MessageBox(0, _T("创建服务失败,未能获取应用程序当前的路径"), m_ServiceName.c_str(), MB_ICONSTOP);
return false;
}
buffer[written + 1] = '"';
buffer[written + 2] = 0;
hService = CreateService(hScm, m_ServiceName.c_str(),
m_ServiceDisplayName.c_str(),
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, nStartMode,
SERVICE_ERROR_NORMAL,
buffer,
0, 0, NULL, 0, 0);
if (!hService)
{
CloseServiceHandle(hScm);
return false;
}
SERVICE_DESCRIPTION description;
memset(&description, 0, sizeof(SERVICE_DESCRIPTION));
TCHAR szdescription[100];
memset(szdescription, 0, sizeof(TCHAR) * 100);
_stprintf_s(szdescription, 100, _T("%s"), m_ServiceName.c_str());//服务名称
description.lpDescription = szdescription;
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &description);
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
dwCurrentState = SERVICE_STOPPED;
return true;
}
//卸载服务
bool CWindowsService::Uninstall()
{
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if (!hScm)
{
return false;
}
hService = OpenService(hScm, m_ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (!hService)
{
CloseServiceHandle(hScm);
return false;
}
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
return true;
}
//启动服务
bool CWindowsService::Start()
{
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if (!hScm)
{
return false;
}
hService = OpenService(hScm, m_ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (!hService)
{
CloseServiceHandle(hScm);
return false;
}
if (StartService(hService, 0, NULL) == 0)
{
DWORD dwerr = GetLastError();
Sleep(1);
}
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
return true;
}
//停止服务
bool CWindowsService::Stop()
{
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if (!hScm)
{
return false;
}
hService = OpenService(hScm, m_ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (!hService)
{
CloseServiceHandle(hScm);
return false;
}
SERVICE_STATUS status;
ControlService(hService, SERVICE_CONTROL_STOP, &status);
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
return true;
}
//创建服务主要处理逻辑
void CWindowsService::ServiceMain(DWORD argc, LPTSTR * argv)
{
BOOL success;
g_pWindowsService->m_nServiceStatusHandle = RegisterServiceCtrlHandler(g_pWindowsService->m_ServiceName.c_str(), (LPHANDLER_FUNCTION)(ServiceCtrlHandler));
if (!g_pWindowsService->m_nServiceStatusHandle)
return;
success = g_pWindowsService->UpdateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000);
if (!success)
return;
g_pWindowsService->m_EventkillService = CreateEvent(0, TRUE, FALSE, 0);//创建时间等待结束
if (g_pWindowsService->m_EventkillService == NULL)
return;
success = g_pWindowsService->UpdateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
if (!success)
return;
success = g_pWindowsService->StartServiceThread(); //开启主线程
if (!success)
return;
g_pWindowsService->m_dwServiceCurrentStatus = SERVICE_RUNNING;
success = g_pWindowsService->UpdateServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
if (!success)
return;
WaitForSingleObject(g_pWindowsService->m_EventkillService, INFINITE); //等待结束
CloseHandle(g_pWindowsService->m_EventkillService);
WaitForSingleObject(g_pWindowsService->m_hServiceThread, INFINITE); // 更待结束线程结束
CloseHandle(g_pWindowsService->m_hServiceThread);
g_pWindowsService->UpdateServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
}
//接受servicecontrol 命令
void CWindowsService::ServiceCtrlHandler(DWORD nControlCode)
{
BOOL success;
switch (nControlCode)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
g_pWindowsService->m_dwServiceCurrentStatus = SERVICE_STOP_PENDING;
success = g_pWindowsService->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 3000);
g_pWindowsService->KillService();
return;
default:
break;
}
g_pWindowsService->UpdateServiceStatus(g_pWindowsService->m_dwServiceCurrentStatus, NO_ERROR, 0, 0, 0);
}
//更新服务状态 更新失败即结束服务
BOOL CWindowsService::UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
{
BOOL success;
SERVICE_STATUS nServiceStatus;
nServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
nServiceStatus.dwCurrentState = dwCurrentState;
if (dwCurrentState == SERVICE_START_PENDING)
{
nServiceStatus.dwControlsAccepted = 0;
}
else
{
nServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN;
}
if (dwServiceSpecificExitCode == 0)
{
nServiceStatus.dwWin32ExitCode = dwWin32ExitCode;
}
else
{
nServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
}
nServiceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
nServiceStatus.dwCheckPoint = dwCheckPoint;
nServiceStatus.dwWaitHint = dwWaitHint;
success = SetServiceStatus(m_nServiceStatusHandle, &nServiceStatus);
if (!success)
{
KillService();
return success;
}
else
{
return success;
}
}
//创建主窗口线程
BOOL CWindowsService::StartServiceThread()
{
DWORD id;
m_hServiceThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ServiceExecutionThread, 0, 0, &id);
if (m_hServiceThread == 0)
{
return FALSE;
}
else
{
m_bServiceRunning = TRUE;
return true;
}
}
//创建服务主线程(应用主要启动)
DWORD CWindowsService::ServiceExecutionThread(LPDWORD param)
{
BOOL res = TRUE;
//启动
CServer *pServer = new CServer;
g_pWindowsService->m_bServiceRunning = pServer->Create();
if (!g_pWindowsService->m_bServiceRunning)
{
return 0;
}
else
{
g_pWindowsService->m_hMain = pServer->GetMainHwnd();
}
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
SetEvent(g_pWindowsService->m_EventkillService);
return 0;
}
// 停止服务 即结束主窗口线程 设置状态失败或是收到STOP SERVICE 命令调用此函数
void CWindowsService::KillService()
{
if (m_hMain != NULL)
PostMessage(m_hMain, WM_CLOSE, 0, 0); //结束窗口
m_bServiceRunning = FALSE;
}
- 需要修改地方
WindowsService.cpp
//创建服务主线程(应用主要启动)
DWORD CWindowsService::ServiceExecutionThread(LPDWORD param)
修改该函数里面的
//启动
CServer *pServer = new CServer;
g_pWindowsService->m_bServiceRunning = pServer->Create();
这里就是服务真正需要运行的代码,对应修改。
- 调用方式
#include "stdafx.h"
#include "WindowsService.h"
#ifndef _DEBUG
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
#endif
int _tmain(int argc, _TCHAR* argv[])
{
#ifdef _DEBUG//调试
//调试使用
#else//服务(发布使用)
//设置服务名称
string strServiceName = "ServiceName";
g_pWindowsService = new CWindowsService(strServiceName);
g_pWindowsService->Run();//注册服务,启动
#endif
return 0;
}