错误 1053:服务没有及时响应启动或控制请求。

75

我最近接手了几个作为Windows服务运行的应用程序,但我无法在系统托盘的上下文菜单中提供gui界面。

我们需要为Windows服务提供gui界面是为了能够重新配置Windows服务的行为而无需停止/重新启动服务。

我的代码在调试模式下正常工作,我可以得到上下文菜单并且一切都表现正确。

当我使用指定账户(即非本地系统账户)通过"installutil"安装服务时,服务可以正常运行,但没有在系统托盘中显示图标(我知道这是正常行为,因为我没有"与桌面交互"选项)。

问题在于-当我选择"LocalSystemAccount"选项并选中"与桌面交互"选项时,该服务需要很长时间才能启动,原因不明,我不断收到以下错误:

无法在本地计算机上启动...服务。

错误1053:服务没有按时响应启动或控制请求。

顺便说一下,我通过注册表修改(参见http://support.microsoft.com/kb/824344,在第3部分中搜索TimeoutPeriod)将Windows服务超时时间从默认的30秒增加到2分钟,但服务启动仍然超时。

我的第一个问题是-为什么"Local System Account"登录比服务日志中非本地系统账户花费时间更长,导致Windows服务超时?这两者之间的区别是什么,会导致在启动时表现如此不同?

第二点 - 退一步说,我想实现的只是一个提供GUI配置的Windows服务 - 如果可以让服务与桌面交互(即从系统托盘中提供上下文菜单),我很乐意使用非Local System帐户(使用已命名的用户名/密码)。 这是否可能? 如果可以,应该如何实现?
感谢任何关于上述问题的指导!

这是微软关于此错误的说法:http://support.microsoft.com/kb/307806/en-us - user1193035
你的应用程序配置文件中是否有一个或多个加密部分?我在特定的机器上遇到了同样的问题。在检查和尝试了几乎所有的方法后,我尝试将服务部署到该机器上,但没有加密任何部分,这对我起作用了。 - Vishal
如果您尚未为服务指定“启动对象”,则可能会出现此错误。首先卸载该服务。然后,在Visual Studio中,右键单击服务的项目文件并选择“属性”。在“应用程序”选项卡下,使用下拉列表设置“启动对象”,方法是选择“Program.cs”中定义的命名空间限定类名称用于“Program”类。例如,MyNamespace.MyProject.Program。现在在Visual Studio中重新构建项目(可以使用调试构建),然后重试安装。 - Chris Halcrow
34个回答

79

经过几天的尝试后,我的一位朋友告诉我必须使用Release版本。如果我在安装Debug版本时使用InstallUtil,则会出现此消息。但是Release版本可以正常启动。


5
马蒂,你的朋友有没有告诉你为什么需要这样做?我也遇到了同样的问题,但不知道为什么这样做可以解决它,让人感到非常不满意。 - khargoosh
1
我在发布版本中也收到了相同的消息。 - King_Fisher
嗨@King_Fisher,你解决了这个问题吗?因为我在发布版本中遇到了同样的问题。 - Dhawal
@Dhawal - 我之前在同时运行多个任务时遇到了问题,导致服务停止。因此,我使用了线程来独立运行。 - King_Fisher
以发布模式构建项目 - Roshan

31
如果您继续尝试使您的服务直接与用户的桌面交互,那么您将会失败:即使在最好的情况下(即“Vista”之前),这也是非常棘手的。Windows内部管理几个window stations,每个窗口站都有自己的桌面。分配给特定帐户下运行的服务的窗口站与已登录的交互式用户的窗口站完全不同。跨窗口站访问一直被视为安全风险,但以前的Windows版本允许一些例外情况,但这些在Vista和后来的操作系统中大多被消除了。
您的服务在启动时挂起的最可能原因是,它正在尝试与不存在的桌面交互(或者假设Explorer正在系统用户会话内运行,这也不是事实),或者正在等待来自不可见桌面的输入。
唯一可靠的解决这些问题的方法是从您的服务中消除所有UI代码,并将其移动到在交互式用户会话内运行的单独可执行文件中(例如,可以使用全局启动组启动可执行文件)。您的UI代码和服务之间的通信可以使用任何RPC机制来实现:命名管道非常适用于此目的。如果您的通信需求很少,使用application-defined Service Control Manager commands也可能起到作用。
要实现UI和服务代码之间的这种分离需要一些努力:但是,这是使事情可靠工作的唯一方法,并且将在未来为您提供帮助。

附录,2010年4月: 由于这个问题仍然非常流行,这里提供一种解决另一个常见情况的方法,该情况会导致“服务未响应...”错误,涉及到不尝试任何有趣的事情(如与桌面交互)但使用 Authenticode签名程序集的.NET服务:在加载时禁用Authenticode签名的验证以创建发布者证据,通过向.exe.config文件添加以下元素:

<configuration>
    <runtime>
        <generatePublisherEvidence enabled="false"/>
    </runtime>
</configuration>

出版商证书是一个很少使用的代码访问安全(CAS)功能:只有在您的服务实际上依赖于PublisherMembershipCondition时,禁用它才会导致问题。在所有其他情况下,通过不再需要运行时执行昂贵的证书检查(包括撤销列表查找),可以使永久或间歇性的启动故障消失。

我的服务没有用户交互,但我仍然遇到了错误...似乎尝试安装服务的调试版本也会导致一些问题。不要这样做... - Ortund
@Ortund,似乎发布版本的Windows服务对于解决许多此类问题至关重要。您知道是什么原因/有何区别吗? - khargoosh
我们将GoAhead Web服务器嵌入到我们的服务中,以便我们可以拥有运行时用户界面... https://www.embedthis.com/goahead/download.html 我不是GoAhead的员工,我们只是他们产品的最终用户。 - buzz3791

25

4
我认为这个答案应该排得更靠前 :) - Daniel Persson
那就是问题所在。如果在启动服务时能够得到适当的消息,那将非常有用。我只有在尝试双击服务(它被编译为exe)并提示安装正确版本的.NET后才意识到这一点。 - Nick Patsaris

14

为了调试您的服务的启动过程,请在您的服务的OnStart()方法顶部添加以下内容:

 while(!System.Diagnostics.Debugger.IsAttached) Thread.Sleep(100);

使用 Debug -> Attach to Process... 手动附加 Visual Studio 调试器会使服务停止运行。

注意: 一般情况下,如果需要用户与您的服务交互,最好将 GUI 组件拆分为单独的 Windows 应用程序,在用户登录时运行。然后,您可以使用命名管道或其他形式的 IPC 来建立 GUI 应用程序和服务之间的通信。实际上,这是在 Windows Vista 系统中唯一可能的方法。


那可能会起作用,我还没有尝试过。不过我有一种感觉,可能有原因... - Jacob

7

在OnStart方法内的服务类中,不要进行大量的操作,操作时间应该尽可能短,使用线程启动运行您的方法:

protected override void OnStart(string[] args)
{
    Thread t = new Thead(new ThreadStart(MethodName)); // e.g.
    t.Start();
}

你好,当我遇到问题时,我发现你的解决方案非常有用。我在http://support.microsoft.com/kb/307806上找到了实际的问题,但我无法理解你的解决方案是如何克服这个问题的。能否请您解释一下? - nishantv
这为我省去了一场噩梦,我曾试图在"OnStart"中启动一个永无止境的"while(true)"循环。它给了我这个1053错误。OnStart需要调用一个简短而甜美的方法调用。 - Dhanuka777

5
我在这里摸索,但我经常发现服务启动时长时间的延迟直接或间接地由网络功能超时引起,通常是在尝试联系域控制器查找帐户SID时发生,这经常是通过GetMachineAccountSid()间接调用RPC子系统时发生,无论您是否意识到它。

如果您需要在这种情况下进行调试,请参阅Mark Russinovich的博客“进程启动延迟案例”中的示例。


这里也有同样的问题 - 原来我的服务引用的DLL中有一个被标记为“web”,因此被阻止了。无论是杀毒软件还是组策略都防止服务启动(30秒内甚至没有调用CTor或OnStart())。解除引用程序集的阻止(https://dev59.com/VnA75IYBdhLWcg3w186G)解决了这个问题。这似乎可以通过Mark Russinovich的文章来解释。 - StuartLC

4
如果您在服务中使用以下调试代码,则可能会出现问题。
#if(!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new EmailService()
};
ServiceBase.Run(ServicesToRun);
#else
//direct call function what you need to run
#endif

为解决此问题,请在构建 Windows 服务时删除 #if 条件,因为它无法正常工作。请改用以下方式进行调试模式的参数传递。
if (args != null && args.Length > 0)
{
_isDebug = args[0].ToLower().Contains("debug");
}

4
在我的情况下,问题是缺少了.net framework的版本。

我的服务使用了

<startup>
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>

但是服务器上的.net Framework版本是4,所以将4.5改为4后问题得到解决:

<startup>
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>

3

在此输入图片描述

我花了几个小时才发现问题出在get_AppSettings()上,应该先查看事件查看器。

应用程序配置的更改导致了这个问题。


这是什么事件日志?如何找到它? - Filomat
1
在Windows服务器上打开“事件查看器”。展开Windows应用程序,然后展开第一个选项。 - AJ AJ

3

复制发行版DLL或从发行模式获取DLL,然后将其粘贴到安装文件夹中,而不是调试模式,它应该可以工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接