错误1053:服务未及时响应启动或者控制请求
我最近继承了几个作为Windows服务运行的应用程序,而我在为这两个应用程序提供gui(可从系统任务栏的上下文菜单访问)时遇到问题。
我们需要Windows服务的GUI的原因是为了能够重新配置Windows服务的行为,而无需诉诸停止/重新启动。
我的代码在调试模式下运行良好,出现了上下文菜单,并且一切正常。
当我使用命名帐户(即不是本地系统帐户)通过" installutil"安装服务时,该服务运行良好,但未在系统任务栏中显示该图标(我知道这是正常现象,因为我没有具有"与桌面互动"选项)。
这是问题所在,但是当我选择" LocalSystemAccount"选项并选中"与桌面交互"选项时,该服务会启动AGES进行启动,而没有明显的原因,而我一直在获取
Could not start the ... service on Local Computer. Error 1053: the service did not respond to the start or control request in a timely fashion.
顺便说一句,我通过注册表黑客将Windows服务超时从默认的30秒增加到2分钟(请参阅http://support.microsoft.com/kb/824344,在第3节中搜索TimeoutPeriod),但是该服务仍会启动超时。
我的第一个问题是,为什么与使用非LocalSystemAccount登录服务时相比,"本地系统帐户"登录会占用SOOOOO更长的时间,从而导致Windows服务超时?这两者之间有什么区别,从而在启动时导致如此不同的行为?
第二步,我要实现的目标只是一个Windows服务,该服务提供配置的GUI,如果我愿意使用非本地系统帐户(具有命名的user / pwd)运行,我将非常高兴。可以使该服务与桌面进行交互(即,从系统任务栏中提供上下文菜单)。这可能吗?如果可以,怎么办?
任何指向上述问题的指针,将不胜感激!
解决方案
安装服务的调试版本,并将调试器添加到服务,以查看发生了什么。
我在这里视而不见,但是我经常发现服务启动的长时间延迟是由网络功能超时直接或者间接引起的,经常是当试图在查找帐户SID时联系域控制器时,这通常是通过间接发生的无论我们是否意识到,GetMachineAccountSid()
,因为该功能由RPC子系统调用。
有关如何在这种情况下进行调试的示例,请参见Mark Russinovich的博客上的"过程启动延迟的情况"。
如果继续尝试使服务直接与用户的桌面交互,那么我们将会迷失方向:即使在最佳情况下(例如"在Vista之前"),这也非常棘手。
Windows在内部管理多个窗口站,每个窗口站都有自己的桌面。分配给在给定帐户下运行的服务的窗口站与已登录的交互式用户的窗口站完全不同。跨窗口工作站访问一直被禁止,因为它存在安全风险,但是尽管以前的Windows版本允许某些例外,但在Vista和更高版本的操作系统中大多已消除了这些例外。
服务在启动时挂起的最可能原因是,它正在尝试与不存在的桌面进行交互(或者假设Explorer在系统用户会话中运行,事实并非如此),或者正在等待来自不可见桌面的输入。
解决这些问题的唯一可靠方法是从服务中删除所有UI代码,并将其移至在交互式用户会话中运行的单独可执行文件(例如,可以使用全局启动组来启动该可执行文件)。
可以使用任何RPC机制来实现UI代码与服务之间的通信:命名管道在此方面特别有效。如果通信需求很少,则使用应用程序定义的Service Control Manager命令也可以解决问题。
要实现UI和服务代码之间的这种分离需要花费一些精力:但是,这是使事情可靠运行的唯一方法,并且将来会为我们提供良好的服务。
附录,2010年4月:由于此问题仍然很流行,因此,这是一种解决导致"服务未响应..."错误的常见情况的方法,该错误涉及涉及.NET服务的内容,不会尝试任何有趣的事情,例如与桌面交互,但请使用Authenticode签名的程序集:在加载时禁用Authenticode签名的验证,以便创建发布者证据,方法是将以下元素添加到.exe.config文件中:
<configuration> <runtime> <generatePublisherEvidence enabled="false"/> </runtime> </configuration>
发布者证据是很少使用的代码访问安全性(CAS)功能:仅在极少数情况下服务实际上依赖PublisherMembershipCondition才会禁用它,从而导致问题。在所有其他情况下,它将不再需要运行时进行昂贵的证书检查(包括吊销列表查找),从而消除了永久性或者间歇性启动失败。
要调试服务的启动,请将以下内容添加到服务的OnStart()方法的顶部:
while(!System.Diagnostics.Debugger.IsAttached) Thread.Sleep(100);
这将停止服务,直到我们使用Debug-> Attach to Process ...手动添加Visual Studio Debugger为止。
注意:通常,如果需要用户与服务进行交互,最好将GUI组件拆分为一个单独的Windows应用程序,该应用程序在用户登录时运行。然后使用诸如命名管道或者其他形式的IPC之类的东西在GUI应用程序和服务之间建立通信。实际上,这是在Windows Vista中实现此目标的唯一方法。
我想在这里回应mdb的评论。不要走这条路。服务不应该具有UI ..."无用户交互"就像是服务的定义功能。
如果需要配置服务,请编写另一个应用程序,该应用程序将编辑该服务在启动时读取的相同配置。但是,使其成为一个独特的工具-当我们要启动该服务时,就可以启动该服务。要配置它时,请运行配置工具。
现在,如果我们需要对服务进行实时监控,那就有些棘手了(当然我也希望对服务有所了解)。现在,我们正在谈论必须使用进程间通信和其他令人头疼的问题。
最糟糕的是,如果我们需要用户交互,那么这里确实存在断开连接,因为服务不会与用户交互。
我穿上鞋子后退一步,问为什么这需要服务?为何需要用户交互?
这两个要求非常不兼容,应该发出警报。
我也有这个问题。我通过将"登录"帐户更改为"本地系统帐户"来使其正常工作。在我的项目中,我将其设置为以本地服务帐户身份运行。因此,当我安装它时,默认情况下它使用的是本地服务。我正在使用.net 2.0和VS2005. 因此,安装.net 1.1 SP1不会有帮助。
本地系统帐户和本地服务都不适合我,然后我将其设置为网络服务,这很好。