淘宝店遇到客户如下咨询:

具体情况如下:
客户用 Qt 的 Core Network 写了个控制台程序,通过 QTcpServer 监听客户端连接,实现一些功能
直接作为 exe 双击运行,没啥问题,但客户现在想注册为 Windows 服务,却发现能启动,但是客户端连不上。
其实直接原因是客户把控制台程序 强行注册成服务
很多人一开始是这么干的:
写了一个正常的 Qt 控制台程序:
91int main(int argc, char *argv[])2{3 QCoreApplication a(argc, argv);4
5 QTcpServer server;6 server.listen(QHostAddress::Any, 12345);7
8 return a.exec();9}然后用 sc create 或者服务安装工具,直接把这个 exe 注册成服务:
11sc create MyQtServer binPath= "C:\xxx\myserver.exe"表面上看:
服务管理器里出现了 MyQtServer
点“启动”时,系统确实会拉起这个进程
但问题是: 你的程序从头到尾,都只是一个“普通 EXE”,根本没有按照服务的规范跟系统打招呼,所以:
服务控制管理器(SCM)看你一直没“回应”它,就认为: 这个服务没按照规矩启动/没响应我的启动命令
于是给你一个 1053 之类的错误:服务没有及时响应启动或控制请求
有的情况下系统会把你进程直接杀掉,你以为在跑,其实已经没了
这就是我说的:
你只是把控制台程序强行注册成服务
一个合格的 Windows 服务程序,至少要做这些步骤(简化版):
程序入口(main / WinMain)里调用:
11StartServiceCtrlDispatcher(serviceTable);告诉系统: 我支持服务模式,你可以把客户端请求(启动/停止等)派发给我。
提供一个 ServiceMain 函数(就是那个接口/回调):
41void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)2{3 // 这里才是真正的“服务主体”4}当你在“服务”里点启动时,SCM 会在某个线程里调用这个 ServiceMain。
在 ServiceMain 里你要做:
调 RegisterServiceCtrlHandler 注册一个控制回调,用于接收“停止、暂停”等命令;
调 SetServiceStatus 报告当前服务状态:
刚开始:SERVICE_START_PENDING(正在启动)
准备好了:SERVICE_RUNNING(已经运行)
在适当的时候(通常是自己的事件循环退出后)再报告 SERVICE_STOPPED。
Service 控制回调里要能处理停止命令:
61void WINAPI ServiceCtrlHandler(DWORD control)2{3 if (control == SERVICE_CONTROL_STOP) {4 // 通知你的主循环退出(比如 Qt 的 app.quit())5 }6}只有做完这些事情,SCM 才认为你是一个“正经服务”,并且能正常管理你。
nssm 全称 Non-Sucking Service Manager
是Windows环境下一款免安装的服务管理软件,它可以将应用封装成服务
即将普通 exe程序 或者 jar包 应用封装成服务使之像windows服务可以设置自动启动等。
并且可以监控程序运行状态,程序异常中断后自动启动,实现守护进程的功能。
官网地址 nssm.cc
git地址 https://git.nssm.cc/nssm/nssm

NSSM常用命令,如下:
安装服务:nssm install 服务名称
删除服务:nssm remove 服务名称
删除服务确定:nssm remove 服务名称 confirm
修改服务:nssm edit 服务名称
启动服务:nssm start 服务名称
停止服务:nssm stop 服务名称
最后客户使用了 NSSM 解决了他的问题