赞
踩
参考博客:
C++调用StartService启动服务失败1053分析与解决
StartServiceCtrlDispatcher函数
指定的服务已标记为删除
安装和卸载服务
windows服务开发分为两个步骤:
.exe
services.msc
里面可以看见自己的服务问:为什么需要编写服务程序?是不是随便一个exe都可以作为服务程序运行?
答:服务程序必须主动调用StartServiceCtrlDispatcher
上报自己的当前状态,否则服务控制台由于不知道服务的运行状态的而报错,例如:StartService启动服务失败1053。所以开发服务程序的时候我们必须通过StartServiceCtrlDispatcher
上报状态并且处理服务事件。
StartServiceCtrlDispatcher
,设置服务事件回调。如果程序作为非服务状态运行则会返回错误:ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
,程序会一直阻塞运行,直至SERVICE_STOPPED
状态才返回CMscSvc.h
:
//如果作为服务程序,需要向服务报告自己的状态,否则服务控制台是不知道服务状态,会失败 class CMscSvc { public: //如果作为服务程序,需要注册服务 static void RegisterSvc(std::string msc_name); //上报启动成功事件 static void ReportStart(); //上报停止成功事件 static void ReportStop(); private: //如果作为服务程序需要报告自己的状态 static void ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); //服务主处理函数,内部添加自己的业务逻辑代码。可包装到doWork函数内部 static VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv); //响应服务控制台事件,例如停止 static VOID WINAPI SvcCtrlHandler(DWORD dwCtrl); static SERVICE_STATUS_HANDLE s_gSvcStatusHandle; static SERVICE_STATUS s_gSvcStatus; static std::string m_msc_name; };
CMscSvc.cpp
:
SERVICE_STATUS_HANDLE CMscSvc::s_gSvcStatusHandle; SERVICE_STATUS CMscSvc::s_gSvcStatus; std::string CMscSvc::m_msc_name = ""; void CMscSvc::RegisterSvc(std::string msc_name) { m_msc_name = msc_name; char szName[MAX_PATH] = ""; _stprintf_s<MAX_PATH>(szName, "%s", m_msc_name.c_str()); SERVICE_TABLE_ENTRY DispatchTable[] ={ { szName, (LPSERVICE_MAIN_FUNCTION)SvcMain }, { NULL, NULL }}; if (!StartServiceCtrlDispatcher(DispatchTable)) { DWORD dwErrcode = GetLastError(); DebugPrint(_T("StartServiceCtrlDispatcher failed,errcode:%d"), dwErrcode); } } void CMscSvc::ReportStart() { ReportSvcStatus(SERVICE_RUNNING, 0, 0); } void CMscSvc::ReportStop() { ReportSvcStatus(SERVICE_STOPPED, 0, 0); } VOID WINAPI CMscSvc::SvcMain(DWORD dwArgc, LPTSTR *lpszArgv) { // Register the handler function for the service s_gSvcStatusHandle = RegisterServiceCtrlHandler(m_msc_name.c_str(), SvcCtrlHandler); if (!s_gSvcStatusHandle) { DWORD dwErrcode = GetLastError(); DebugPrint(_T("RegisterServiceCtrlHandler failed,errcode:%d"), dwErrcode); return; } // These SERVICE_STATUS members remain as set here s_gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; s_gSvcStatus.dwServiceSpecificExitCode = 0; // Report initial status to the SCM ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); //上报启动成功状态 ReportStart(); //开始处理业务 doWork(); } void CMscSvc::ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) { static DWORD dwCheckPoint = 1; // Fill in the SERVICE_STATUS structure. s_gSvcStatus.dwCurrentState = dwCurrentState; s_gSvcStatus.dwWin32ExitCode = dwWin32ExitCode; s_gSvcStatus.dwWaitHint = dwWaitHint; if (dwCurrentState == SERVICE_START_PENDING) s_gSvcStatus.dwControlsAccepted = 0; else s_gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) s_gSvcStatus.dwCheckPoint = 0; else s_gSvcStatus.dwCheckPoint = dwCheckPoint++; SetServiceStatus(s_gSvcStatusHandle, &s_gSvcStatus); } //每当使用controlService函数向服务发送控制代码时,由SCM调用 VOID WINAPI CMscSvc::SvcCtrlHandler(DWORD dwCtrl) { // Handle the requested control code. switch (dwCtrl) { case SERVICE_CONTROL_STOP: { ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); //退出业务处理逻辑 exitWork() //上报停止状态成功 ReportStop() return; } case SERVICE_CONTROL_INTERROGATE: break; default: break; } }
调用
void _main()
{
CMscSvc::RegisterSvc("testSvr");
}
注意步骤:
OpenSCManager
CreateService
OpenService
StartService
QueryServiceStatus
CMsc.h
:
class CMsc
{
public:
CMsc(std::string msc_name,std::string exe_full_path,std::string exe_param = "",std::string msc_desc = "");
~CMsc();
BOOL start();
BOOL stop(BOOL bUnInstall = FALSE/*是否卸载*/);
private:
std::string m_msc_name;
std::string m_msc_display_name;
std::string m_msc_desc;
std::string m_exe_cmd;
};
CMsc.cpp
:
class CSafeSCHandle { public: CSafeSCHandle(const SC_HANDLE& hscm) :m_hscm(hscm){}; ~CSafeSCHandle() { if (m_hscm) { CloseServiceHandle(m_hscm); } } operator const SC_HANDLE&(){ return m_hscm; } private: const SC_HANDLE &m_hscm; }; CMsc::CMsc(std::string msc_name,std::string exe_full_path, std::string exe_param) { m_msc_name = msc_name; m_msc_display_name = m_msc_name; m_exe_cmd = exe_full_path + _T(" ") + exe_param; m_msc_desc = msc_desc; DebugPrint("CMsc name:%s,exe_full_path:%s,exe_param:%s", m_msc_name.c_str(), exe_full_path.c_str(), exe_param.c_str()); } CMsc::~CMsc() { } BOOL CMsc::start() { //打开msc服务管理器 CSafeSCHandle hScm(OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)); if (hScm == NULL) { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,start,OpenSCManager failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } //如果服务已经存在则直接start CSafeSCHandle hService(OpenService(hScm, m_msc_name.c_str(), SERVICE_ALL_ACCESS)); if (hService != NULL) { SERVICE_STATUS status; QueryServiceStatus(hService, &status); if (status.dwCurrentState == SERVICE_RUNNING) { return TRUE; } if (StartService(hService, 0, NULL)) { DebugPrint("CMsc name:%s,start,StartService OK", m_msc_name.c_str()); return TRUE; } else { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,start,StartService failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } } //如果服务不存在则创建 CSafeSCHandle hCService(CreateService(hScm, m_msc_name.c_str(), m_msc_display_name.c_str(), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, m_exe_cmd.c_str(), NULL, NULL, "", NULL, "")); if (hCService == NULL) { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,start,CreateService failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } //设置服务描述 if (!m_msc_desc.empty()) { SERVICE_DESCRIPTION sd; sd.lpDescription = (char *)m_msc_desc.c_str(); ChangeServiceConfig2(hCService, SERVICE_CONFIG_DESCRIPTION, &sd); } SERVICE_STATUS status; QueryServiceStatus(hCService, &status); if (status.dwCurrentState == SERVICE_RUNNING) { DebugPrint("CMsc name:%s,start,StartService OK,is already runing", m_msc_name.c_str()); return TRUE; } if (StartService(hCService, 0, NULL)) { DebugPrint("CMsc name:%s,start,StartService OK", m_msc_name.c_str()); return TRUE; } else { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,start,StartService failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } } BOOL CMsc::stop(BOOL bUnInstall) { //打开msc服务管理器 CSafeSCHandle hScm(OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)); if (hScm == NULL) { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,stop,OpenSCManager failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } //如果服务已经存在则直接start CSafeSCHandle hService(OpenService(hScm, m_msc_name.c_str(), SERVICE_ALL_ACCESS)); if (hService == NULL) { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,stop,OpenService failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } //查询服务状态 SERVICE_STATUS status; QueryServiceStatus(hService, &status); if (status.dwCurrentState == SERVICE_RUNNING) { //停止服务 ControlService(hService, SERVICE_CONTROL_STOP, &status); if (status.dwCurrentState != NO_ERROR) { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,stop,ControlService failed,errcode:%d", m_msc_name.c_str(), dwErrcode); return FALSE; } } //如果卸载服务 if (bUnInstall && status.dwCurrentState == SERVICE_STOPPED) { if (DeleteService(hService)) { DebugPrint("CMsc name:%s,stop,DeleteService OK", m_msc_name.c_str()); } else { DWORD dwErrcode = GetLastError(); DebugPrint("CMsc name:%s,stop,DeleteService failed,errcode:%d", m_msc_name.c_str(), dwErrcode); } } DebugPrint("CMsc name:%s,stop,ControlService OK", m_msc_name.c_str()); return TRUE; }
调用
void _main()
{
//msc_name-服务名称
//exe_full_path exe的全路径
//exe_params exe的执行参数
CMsc msc(msc_name, exe_full_path, "exe_params");
//安装并启动服务
msc.start();
//停止并且卸载服务
msc.stop(TRUE);
}
此时我们就可以安装服务程序,并且在services.msc
中查看了。
Note:如果服务管理器打开了,则删除服务管理器会失败[指定的服务已标记为删除]。必须关闭重试。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。