我已尝试使用 StartServiceCtrlDispatcher(),如 https://msdn.microsoft.com/en-us/library/windows/desktop/bb540475(v=vs.85).aspx 中所述, 它可以工作,只是参数不会传递给 SvcMain。我可以使用 StartService() 来解决这个问题吗?这两种启动服务的方法除了 StartService() 似乎需要的额外代码外还有其他区别吗?
最佳答案
这是服务启动的方式:
首先,某些进程必须调用 StartService() 以告知服务控制管理器 (SCM) 应该启动该服务。这可能是 Windows 本身(如果服务配置为自动启动或为了启动依赖服务)或者它可能是服务管理工具、
net start
命令或应用程序。无论哪个进程调用 StartService 都可以为服务设置参数。这些参数最终将传递给 ServiceMain()。注意:这些参数从未传递给 main()。
如果是 Windows 调用 StartService,则不传递任何参数。
SCM 运行服务应用程序命令,该命令在创建服务时设置。这是 CreateService() 调用的
lpBinaryPathName
参数,如果您使用sc create
命令,也称为binpath
。如果命令包含命令行参数,这些将以通常的方式传递给 main()。注意:这些参数从不传递给 ServiceMain()。
主函数必须调用 StartServiceCtrlDispatcher() 来运行服务控制调度程序,它提供 SCM 和服务进程之间的连接。如果应用程序不调用 StartServiceCtrlDispatcher(),您将收到“服务未及时响应启动或控制请求”。错误。
服务控制调度程序根据来自 SCM 的指令执行操作,使用通过调用 StartService() 设置的参数调用 ServiceMain()。
ServiceMain() 或由它启动的线程然后执行实际工作,包括在必要时将服务状态通知 SCM。
您会注意到有两组不同的参数:
StartService() 设置的参数传递给 ServiceMain()。
CreateService() 或 ChangeServiceConfig() 设置的参数,传递给 main()。
它们有不同的用途。如果您需要在安装服务时配置一些东西,您可以使用 main() 的参数。如果您需要在服务启动时配置一些东西,您可以使用 ServiceMain() 的参数。或者你当然可以两者都做;只是不要让他们感到困惑!
通常,ServiceMain() 参数仅供设计为与常规应用程序协同工作并由该应用程序启动的服务使用。
请注意,main() 不能通过调用 StartService() 更改传递给 ServiceMain() 的参数,至少有两个原因:首先,为时已晚,因为启动请求已经被处理,因此参数是已经设置;其次,在服务初始化期间,SCM 数据库被锁定,因此尝试调用 StartService() 将导致死锁。
(如果 Windows 为我们提供了一些配置默认参数或覆盖指定参数的方法,那就太好了。但是在这种情况下确实没有任何理由不使用全局变量:应用程序的命令行是 本质上对应用程序来说是全局的,因此使用全局变量在哲学上是合理的。)
吹毛求疵的角落:事实上,当服务配置为自动启动或必须启动服务依赖项时,Windows 可能不会真正调用 StartService; SCM 更有可能调用等效的内部函数。但结果是一样的。
关于c - 使用 StartServiceCtrlDispatcher 从 C 启动 Windows 服务与 StartService 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33929255/