当我使用 Verisign signtool.exe 对我的服务中的程序集进行签名时,它在机器启动时无法在运行 Windows 2003 Server 的机器上启动。事件日志有两个事件:
“超时(30000 毫秒)等待 xxx Service 服务连接。” 和“由于以下错误导致xxx Service服务启动失败:该服务没有及时响应启动或控制请求。”
一旦机器运行,它就可以正常启动。它在 XP 和 Vista 中启动良好。当程序集未签名时,它开始正常。
当我使用 Verisign signtool.exe 对我的服务中的程序集进行签名时,它在机器启动时无法在运行 Windows 2003 Server 的机器上启动。事件日志有两个事件:
“超时(30000 毫秒)等待 xxx Service 服务连接。” 和“由于以下错误导致xxx Service服务启动失败:该服务没有及时响应启动或控制请求。”
一旦机器运行,它就可以正常启动。它在 XP 和 Vista 中启动良好。当程序集未签名时,它开始正常。
This problem is very common for signed .NET service executables: the service will fail to start at boot time, but run fine when started manually afterwards. Whether ServiceBase.RequestAdditionalTime is used is irrelevant: in fact, no user code is executed at all prior to the service start request timing out. This effect is even more pronounced on machines without Internet connectivity: in that case, even manually starting the service from the SCM will fail.
To resolve this issue, disable the verification of the Authenticode signature at load time in order to create Publisher evidence, by adding the following elements to your .exe.config file:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
Publisher evidence is a little-used Code Access Security (CAS) feature: only if your service relies on the PublisherMembershipCondition will disabling it cause issues. In all other cases, it will make the permanent or intermittent startup failures go away, by no longer requiring the runtime to do expensive certificate checks (including revocation list lookups).
Edit, July 2010: For applications using version 4.0 of the .NET Framework, this workaround is no longer required.
Authenticode 对您的程序集进行签名可能会对冷启动产生非常负面的影响。有关详细信息,请参阅此知识库文章。
正如 spacedog 所说,Authenticode 会对启动时间产生不良影响。所以问题是你签的是什么?仅对您的服务可执行文件进行 Authenticode 签名就足够了,而该可执行文件又必须仅引用强命名程序集。因此验证 Authenticode 签名的开销。
您可以将您的程序集安装到 GAC - 如果可能的话 - 这将略微提高启动性能,因为跳过了强名称验证(请参阅Authenticode 和程序集)和/或如果启动时间仍然是一个问题,您也可以生成您的程序集。
从Romulo A. Ceccon对Windows 服务启动超时的回答:
最好尽快完成启动服务。所以,在启动状态下,只做你绝对需要确认它启动成功的事情;其余的稍后再做。如果启动仍然是一个漫长的过程,请定期使用 SetServiceStatus 通知服务控制管理器您尚未完成,因此它不会使您的服务超时。
除此之外,SetServiceStatus您还可以尝试通过调用ServiceBase.RequestAdditionalTime.