class WindowsService {
private:
SERVICE_STATUS* ServiceStatus = NULL;
SERVICE_STATUS_HANDLE* ServieStutusHandle = NULL;
DWORD dwCheckPoint = 1;
public:
string ServiceName;
string ServicePath;
string ServiceDescription;
WindowsService(string serviceName, string servicePath, string serviceDescription)
:ServiceName(serviceName), ServicePath(servicePath), ServiceDescription(serviceDescription) {
}
/// <summary>
/// 检查服务是否已存在
/// </summary>
/// <returns>
/// 返回码:
/// NO_ERROR,服务存在;
/// ERROR_SERVICE_DOES_NOT_EXIST,服务不存在;
/// 错误码(详见winerror.h)
/// </returns>
DWORD IsInstalled() {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_QUERY_STATUS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 安装服务
/// </summary>
/// <param name="startType">启动方式:SERVICE_AUTO_START、SERVICE_BOOT_START、SERVICE_DEMAND_START、SERVICE_DISABLED、SERVICE_SYSTEM_START</param>
/// <param name="startType">服务运行失败后是否自动重启</param>
/// <returns>
/// 返回码:
/// NO_ERROR,服务安装成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Install(DWORD startType = SERVICE_AUTO_START, bool autoRestart = false) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(
NULL,
NULL,
err = GetLastError();
goto End;
}
schService = CreateServiceA(
schSCManager,
ServiceName.c_str(),
ServiceName.c_str(),
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
startType,
SERVICE_ERROR_NORMAL,
ServicePath.c_str(),
NULL,
NULL,
NULL,
NULL,
NULL);
if (schService == NULL) {
err = GetLastError();
goto End;
}
//设置服务备注信息
if (!ServiceDescription.empty()) {
SERVICE_DESCRIPTIONA sd;
sd.lpDescription = (LPSTR)(ServiceDescription.c_str());
if (!ChangeServiceConfig2A(schService, SERVICE_CONFIG_DESCRIPTION, &sd)) {
err = GetLastError();
goto End;
}
}
//设置服务失败时自动启动
if (autoRestart) {
SERVICE_FAILURE_ACTIONS info;
SC_ACTION action[1];
action[0].Type = SC_ACTION_RESTART;
action[0].Delay = 0;
info.dwResetPeriod = 0; //出现一次失败后,0 ms后重新计算第一次失败
info.lpRebootMsg = NULL;
info.lpCommand = NULL;
info.cActions = 1; // action array个数
info.lpsaActions = action; // action array指针
if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &info)) {
err = GetLastError();
goto End;
}
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 卸载服务
/// </summary>
/// <returns>
/// 返回码:
/// NO_ERROR,服务卸载成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Uninstall() {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), DELETE);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!DeleteService(schService)) {
err = GetLastError();
goto End;
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 启动服务
/// </summary>
/// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
/// <param name="dwTimeout">停止服务等待超时时间(毫秒)</param>
/// <returns>
/// 返回码:
/// NO_ERROR,服务启动成功,服务状态需要通过GetStatus函数获取;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Start(SERVICE_STATUS_PROCESS& ssStatus, DWORD dwTimeout = 30000) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
DWORD dwStartTickCount;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!StartService(schService, 0, NULL)) {
err = GetLastError();
goto End;
}
goto End;
}
dwStartTickCount = GetTickCount();
while (ssStatus.dwCurrentState == SERVICE_START_PENDING) {
Sleep(1000);
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();
goto End;
}
if (GetTickCount() - dwStartTickCount > dwTimeout) {
break;
}
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 停止服务
/// </summary>
/// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
/// <param name="dwTimeout">停止服务等待超时时间(毫秒)</param>
/// <returns>
/// 返回码:
/// NO_ERROR,服务停止成功,服务状态需要通过GetStatus函数获取;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Stop(SERVICE_STATUS_PROCESS& ssStatus, DWORD dwTimeout = 30000) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
DWORD dwStartTickCount;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!ControlService(schService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssStatus)) {
err = GetLastError();
goto End;
}
dwStartTickCount = GetTickCount();
while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
Sleep(1000);
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();
goto End;
}
if (GetTickCount() - dwStartTickCount > dwTimeout) {
break;
}
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 获取服务状态
/// </summary>
/// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
/// <returns>
/// 返回码:
/// NO_ERROR,操作成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD GetStatus(SERVICE_STATUS_PROCESS& ssStatus) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();
goto End;
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
/// Binds the service status.
/// </summary>
/// <param name="serviceStatus">The service status.</param>
/// <param name="servieStutusHandle">The servie stutus handle.</param>
void BindServiceStatus(SERVICE_STATUS& serviceStatus, SERVICE_STATUS_HANDLE& servieStutusHandle) {
ServiceStatus = &serviceStatus;
ServieStutusHandle = &servieStutusHandle;
}
/// <summary>
/// 修改服务状态,
/// 调用此函数之前处理先调用过一次BindServiceStatus才行
/// </summary>
/// <param name="dwCurrentState">服务状态</param>
/// <param name="dwWaitHint">状态变更预计时间(毫秒)</param>
/// <returns>
/// 返回码:
/// NO_ERROR,操作执行成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD ReportServiceStatus(DWORD dwCurrentState, DWORD dwWaitHint, DWORD dwWin32ExitCode = NO_ERROR, DWORD dwServiceSpecificExitCode = NO_ERROR) {
DWORD err = NO_ERROR;
ServiceStatus->dwCurrentState = dwCurrentState;
ServiceStatus->dwWin32ExitCode = dwWin32ExitCode;
ServiceStatus->dwServiceSpecificExitCode = dwServiceSpecificExitCode;
ServiceStatus->dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING) {
ServiceStatus->dwControlsAccepted = 0;
} else {
ServiceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
if (dwCurrentState == SERVICE_RUNNING || dwCurrentState == SERVICE_STOPPED) {
ServiceStatus->dwCheckPoint = 0;
} else {
ServiceStatus->dwCheckPoint = dwCheckPoint++;
}
if (!SetServiceStatus(*ServieStutusHandle, ServiceStatus)) {
err = GetLastError();
return err;
}
return err;
}
};
private:
SERVICE_STATUS* ServiceStatus = NULL;
SERVICE_STATUS_HANDLE* ServieStutusHandle = NULL;
DWORD dwCheckPoint = 1;
public:
string ServiceName;
string ServicePath;
string ServiceDescription;
WindowsService(string serviceName, string servicePath, string serviceDescription)
:ServiceName(serviceName), ServicePath(servicePath), ServiceDescription(serviceDescription) {
}
/// <summary>
/// 检查服务是否已存在
/// </summary>
/// <returns>
/// 返回码:
/// NO_ERROR,服务存在;
/// ERROR_SERVICE_DOES_NOT_EXIST,服务不存在;
/// 错误码(详见winerror.h)
/// </returns>
DWORD IsInstalled() {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_QUERY_STATUS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 安装服务
/// </summary>
/// <param name="startType">启动方式:SERVICE_AUTO_START、SERVICE_BOOT_START、SERVICE_DEMAND_START、SERVICE_DISABLED、SERVICE_SYSTEM_START</param>
/// <param name="startType">服务运行失败后是否自动重启</param>
/// <returns>
/// 返回码:
/// NO_ERROR,服务安装成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Install(DWORD startType = SERVICE_AUTO_START, bool autoRestart = false) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {err = GetLastError();
goto End;
}
schService = CreateServiceA(
schSCManager,
ServiceName.c_str(),
ServiceName.c_str(),
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
startType,
SERVICE_ERROR_NORMAL,
ServicePath.c_str(),
NULL,
NULL,
NULL,
NULL,
NULL);
if (schService == NULL) {
err = GetLastError();
goto End;
}
//设置服务备注信息
if (!ServiceDescription.empty()) {
SERVICE_DESCRIPTIONA sd;
sd.lpDescription = (LPSTR)(ServiceDescription.c_str());
if (!ChangeServiceConfig2A(schService, SERVICE_CONFIG_DESCRIPTION, &sd)) {
err = GetLastError();
goto End;
}
}
//设置服务失败时自动启动
if (autoRestart) {
SERVICE_FAILURE_ACTIONS info;
SC_ACTION action[1];
action[0].Type = SC_ACTION_RESTART;
action[0].Delay = 0;
info.dwResetPeriod = 0; //出现一次失败后,0 ms后重新计算第一次失败
info.lpRebootMsg = NULL;
info.lpCommand = NULL;
info.cActions = 1; // action array个数
info.lpsaActions = action; // action array指针
if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &info)) {
err = GetLastError();
goto End;
}
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 卸载服务
/// </summary>
/// <returns>
/// 返回码:
/// NO_ERROR,服务卸载成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Uninstall() {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), DELETE);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!DeleteService(schService)) {
err = GetLastError();
goto End;
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 启动服务
/// </summary>
/// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
/// <param name="dwTimeout">停止服务等待超时时间(毫秒)</param>
/// <returns>
/// 返回码:
/// NO_ERROR,服务启动成功,服务状态需要通过GetStatus函数获取;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Start(SERVICE_STATUS_PROCESS& ssStatus, DWORD dwTimeout = 30000) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
DWORD dwStartTickCount;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!StartService(schService, 0, NULL)) {
err = GetLastError();
goto End;
}
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();goto End;
}
dwStartTickCount = GetTickCount();
while (ssStatus.dwCurrentState == SERVICE_START_PENDING) {
Sleep(1000);
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();
goto End;
}
if (GetTickCount() - dwStartTickCount > dwTimeout) {
break;
}
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 停止服务
/// </summary>
/// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
/// <param name="dwTimeout">停止服务等待超时时间(毫秒)</param>
/// <returns>
/// 返回码:
/// NO_ERROR,服务停止成功,服务状态需要通过GetStatus函数获取;
/// 错误码(详见winerror.h)
/// </returns>
DWORD Stop(SERVICE_STATUS_PROCESS& ssStatus, DWORD dwTimeout = 30000) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
DWORD dwStartTickCount;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!ControlService(schService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssStatus)) {
err = GetLastError();
goto End;
}
dwStartTickCount = GetTickCount();
while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
Sleep(1000);
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();
goto End;
}
if (GetTickCount() - dwStartTickCount > dwTimeout) {
break;
}
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>
/// 获取服务状态
/// </summary>
/// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
/// <returns>
/// 返回码:
/// NO_ERROR,操作成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD GetStatus(SERVICE_STATUS_PROCESS& ssStatus) {
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
DWORD err = NO_ERROR;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
err = GetLastError();
goto End;
}
schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (schService == NULL) {
err = GetLastError();
goto End;
}
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
err = GetLastError();
goto End;
}
End:
if (schService != NULL) {
CloseServiceHandle(schService);
}
if (schSCManager != NULL) {
CloseServiceHandle(schSCManager);
}
return err;
}
/// <summary>/// Binds the service status.
/// </summary>
/// <param name="serviceStatus">The service status.</param>
/// <param name="servieStutusHandle">The servie stutus handle.</param>
void BindServiceStatus(SERVICE_STATUS& serviceStatus, SERVICE_STATUS_HANDLE& servieStutusHandle) {
ServiceStatus = &serviceStatus;
ServieStutusHandle = &servieStutusHandle;
}
/// <summary>
/// 修改服务状态,
/// 调用此函数之前处理先调用过一次BindServiceStatus才行
/// </summary>
/// <param name="dwCurrentState">服务状态</param>
/// <param name="dwWaitHint">状态变更预计时间(毫秒)</param>
/// <returns>
/// 返回码:
/// NO_ERROR,操作执行成功;
/// 错误码(详见winerror.h)
/// </returns>
DWORD ReportServiceStatus(DWORD dwCurrentState, DWORD dwWaitHint, DWORD dwWin32ExitCode = NO_ERROR, DWORD dwServiceSpecificExitCode = NO_ERROR) {
DWORD err = NO_ERROR;
ServiceStatus->dwCurrentState = dwCurrentState;
ServiceStatus->dwWin32ExitCode = dwWin32ExitCode;
ServiceStatus->dwServiceSpecificExitCode = dwServiceSpecificExitCode;
ServiceStatus->dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING) {
ServiceStatus->dwControlsAccepted = 0;
} else {
ServiceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
if (dwCurrentState == SERVICE_RUNNING || dwCurrentState == SERVICE_STOPPED) {
ServiceStatus->dwCheckPoint = 0;
} else {
ServiceStatus->dwCheckPoint = dwCheckPoint++;
}
if (!SetServiceStatus(*ServieStutusHandle, ServiceStatus)) {
err = GetLastError();
return err;
}
return err;
}
};