windows服务开发
admin
2024-03-24 02:30:32
0

参考博客:
C++调用StartService启动服务失败1053分析与解决
StartServiceCtrlDispatcher函数
指定的服务已标记为删除
安装和卸载服务

windows服务开发分为两个步骤:

  1. 编写服务程序.exe
  2. 安装服务程序,使在services.msc里面可以看见自己的服务

编写服务程序

问:为什么需要编写服务程序?是不是随便一个exe都可以作为服务程序运行?
答:服务程序必须主动调用StartServiceCtrlDispatcher上报自己的当前状态,否则服务控制台由于不知道服务的运行状态的而报错,例如:StartService启动服务失败1053。所以开发服务程序的时候我们必须通过StartServiceCtrlDispatcher上报状态并且处理服务事件。

  1. 调用StartServiceCtrlDispatcher,设置服务事件回调。如果程序作为非服务状态运行则会返回错误:ERROR_FAILED_SERVICE_CONTROLLER_CONNECT,程序会一直阻塞运行,直至SERVICE_STOPPED状态才返回
  2. 注册并相应服务控制事件,例如服务控制台停止事件
  3. 上报服务当前状态

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(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 SCMReportSvcStatus(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");
}

编写服务安装和卸载程序

注意步骤:

  1. 打开服务管理器OpenSCManager
  2. 创建或者打开服务:CreateService OpenService
  3. 启动服务:StartService
  4. 查询服务状态: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;}//如果服务已经存在则直接startCSafeSCHandle 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;}//如果服务已经存在则直接startCSafeSCHandle 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:如果服务管理器打开了,则删除服务管理器会失败[指定的服务已标记为删除]。必须关闭重试。

相关内容

热门资讯

怎么解除订阅安卓系统,安卓系统... 你是不是也和我一样,手机里订阅了好多服务,结果现在想解除订阅,却一头雾水?别急,今天就来手把手教你如...
安卓系统停用怎么开启,轻松恢复... 亲爱的手机控们,你是否曾经遇到过安卓系统突然停用的情况,让你手忙脚乱,不知所措?别担心,今天就来教你...
安卓系统电池健康度,电池健康度... 你有没有发现,你的安卓手机最近是不是有点儿不给力了?电池续航能力大不如前,充电速度也慢了不少?别急,...
安卓系统按键怎么截图,安卓系统... 你是不是也和我一样,有时候想截个图分享给朋友,却发现安卓手机的截图功能有点神秘呢?别急,今天就来手把...
购票系统安卓源代码,架构设计与... 你有没有想过,那些我们每天离不开的购票系统,它们背后的秘密是什么呢?今天,就让我带你一探究竟,揭开购...
安卓手机系统后台测试,深度解析... 你有没有发现,你的安卓手机后台总是悄悄地忙碌着?别小看了这些后台程序,它们可是手机系统稳定运行的关键...
安卓系统重启的图标,解锁设备新... 手机突然重启,是不是心里有点慌?别急,今天就来和你聊聊安卓系统重启的图标,让你一眼就能认出它,再也不...
车载智慧屏安卓系统,智能出行新... 你有没有发现,现在的车载智慧屏越来越智能了?尤其是那些搭载了安卓系统的,简直就像是个移动的小电脑,不...
安卓系统连上网权限,解锁设备无... 你有没有发现,你的安卓手机里有些应用总是偷偷连上网?别小看这个小小的网络权限,它可是能影响你隐私、消...
安卓谷歌操作系统,探索安卓谷歌... 你知道吗?在智能手机的世界里,有一个操作系统可是无人不知、无人不晓,那就是安卓谷歌操作系统。它就像一...
安卓系统手写%怎样调出,具体实... 你有没有遇到过这种情况:在使用安卓手机的时候,突然想用手写输入法来记录一些灵感或者重要信息,可是怎么...
安卓手机重置 系统设置,轻松恢... 手机用久了是不是感觉卡顿得厉害?别急,今天就来教你怎么给安卓手机来个大变身——重置系统设置!想象你的...
win如何安装安卓系统,Win... 哇,你有没有想过,让你的Win系统也能玩转安卓应用?没错,就是那种在手机上轻松自如的安卓系统,现在也...
苹果qq和安卓系统,跨平台体验... 你有没有发现,现在手机市场上,苹果和安卓的较量可是越来越激烈了呢!咱们就来聊聊这个话题,看看苹果QQ...
显示最好的安卓系统,探索最新旗... 你有没有想过,为什么安卓系统那么受欢迎呢?它就像一个魔法盒子,里面装满了各种神奇的魔法。今天,就让我...
安卓app怎么降级系统,系统版... 你有没有发现,有时候安卓手机的系统更新后,新功能虽然炫酷,但老系统用起来更顺手呢?别急,今天就来教你...
雷军脱离安卓系统,引领科技变革... 你知道吗?最近科技圈可是炸开了锅,因为我们的雷军大大竟然宣布要脱离安卓系统,这可真是让人大跌眼镜啊!...
安卓系统自动开网络,安卓系统自... 你有没有发现,手机里的安卓系统有时候会自动开启网络连接,这可真是让人又爱又恨啊!有时候,你正专心致志...
安卓系统怎样控制后台,因为服务... 手机里的安卓系统是不是感觉越来越卡了?后台程序太多,不仅耗电还影响性能。别急,今天就来教你怎么巧妙地...
安卓系统打游戏推荐,一触即达! 你有没有发现,现在手机游戏越来越好玩了?不管是休闲小游戏还是大型MMORPG,都能在手机上畅玩。但是...