我在我的服务/客户端程序中偶然发现了一个严重的问题,该问题的工作方式如下:
ControlService(... SERVICE_CONTROL_STOP ...)
停止服务。QueryServiceStatusEx
以检查dwCurrentState
是否为SERVICE_STOPPED
。它还会检查dwWaitHint
是否超时。同时服务这样做:
SetServiceStatus
= dwCurrentState
和SERVICE_STOP_PENDING
= dwWaitHint
来呼叫3000
。SetServiceStatus
= dwCurrentState
和SERVICE_STOPPED
= dwWaitHint
致电0
。在复制并记录问题后,我想出了这个:
一切正常,除了客户最后一次调用QueryServiceStatusEx
,其返回dwCurrentState
= SERVICE_STOP_PENDING
和dwWaitHint
= {{ 1}}!这使得它的行为就像操作超时一样。
我不知道这是怎么发生的,我可以在日志中清楚地看到服务在退出之前设置0
= dwCurrentState
。
这是一个已知问题吗?你有什么线索可能会发生在这里吗?
更新
以下是客户端应用的日志:
SERVICE_STOPPED
如您所见,该服务已在24437和24546(24437 ssStatus.dwWaitHint: 3000, ssStatus.dwCurrentState: 3
24546 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3
24609 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3
...
26000 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3
26062 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3
26218 Stopped
)之间停止,并且其状态在26218处已更改。这意味着它被标记为GetTickCount
另外1,672秒。 Windows可以改变它的状态吗?为什么它被标记为待定这么久?
更新2:
更多观察:
SERVICE_STOP_PENDING
会影响除SetServiceStatus
之外的所有内容,只要服务进程正在运行,该内容将保留为dwCurrentState
。这是Windows的一个功能吗?是否记录在案?SERVICE_STOP_PENDING
返回后,从LPSERVICE_MAIN_FUNCTION
返回之前,我的服务流程会暂停一两秒钟。为什么会这样? (P.S.它在启动Windows时发生)。StartServiceCtrlDispatcher
,即使它的状态为ERROR_SHARING_VIOLATION
。有没有可靠的方法来确保过程完全结束?有人能解释一下吗?雷蒙德·陈?
更新3:
更有趣的信息:SERVICE_STOPPED
返回dwWaitHint:0,dwCurrentState:3,dwCheckPoint:0即使我从未将QueryServiceStatusEx
和dwWaitHint
设置为零!这是怎么回事?
答案 0 :(得分:1)
我创建了一个简单的服务,并尝试从服务本身查询服务状态,以便查询与状态的变化同步。
SCM要求服务停止。查询状态为SERVICE_RUNNING。该服务将状态设置为SERVICE_STOPPED,再次查询它并获得SERVICE_STOP_PENDING(等待提示为0)。最后,服务在StartServiceCtrlDispatcher返回并获得SERVICE_STOPPED后查询状态。
这不完全一致;这三个查询有两种可能的结果:
SERVICE_RUNNING,SERVICE_STOP_PENDING和SERVICE_STOPPED或
SERVICE_RUNNING,SERVICE_STOPPED和SERVICE_STOPPED。
我在sc
命令行工具中看到了同样的事情。如果我要求它停止我的服务,它有时会将状态报告为已停止,有时会将其报告为待处理状态,即使我的服务从未将其设置为待处理状态。
在服务将状态设置为SERVICE_STOPPED之后,但在Windows将控制权返回给调度程序(主)线程之前,有一个简短的SERVICE_STOP_PENDING窗口。如果机器正在启动并因此繁忙,则此SERVICE_STOP_PENDING窗口可能会很长。
行为是可重复的,似乎是刻意的。但是,正如你所说,它似乎没有在任何地方记录。