德尔福服务无法启动

时间:2015-02-12 22:21:18

标签: delphi service startup

我在使用Delphi编写的服务时遇到问题。它没有开始,我似乎无法找到它的问题。它在2周前运行良好,并且没有任何服务变更,它突然停止工作。 该服务负责更新庞大的系统,但它独立于if。我的服务获取修补程序的URL,下载并执行它。没有更多,没有更少。 它应该更新的系统有一些其他服务和后台运行的东西,所以它有一个小工具可以一次性重启所有后台东西(包括我的服务)。在我的办公室,我们有70台左右的计算机每天运行孔系统,包括我的服务,它工作正常。我们几乎拥有所有版本的Windows(XP,Windows 7,Windows 8,Windows Server 2003甚至Windows 10)。突然有一天,它停止了我告诉你的这个小工具重启。我想到的第一件事就是尝试手动启动,但也没有任何运气。 我最大的问题是,我不知道会发生什么。我可以看到某种日志的唯一地方是在Windows事件管理器中,它根本没用。错误说:

The XXX service failed to start due to the following error: The service did not respond to the start or control request in a timely fashion.

我在网上搜索过,找不到任何有用的东西。与此错误相关的所有页面都表示此错误与Windows服务超时有关,或者与NetFramework 1.1和Windows 2003服务器有关。事实并非如此,我们已经将NetFramework 4与其中一些崩溃的计算机中的最后一次更新进行了对比,正如我告诉你的那样,它可能会在不同版本的Windows中崩溃。关于超时,我在服务管理器中点击启动后立即显示错误,它不会等待30秒超时。

我在服务中有一台日志机,但它没用,错误发生在“ServiceStart”方法之前的某个地方。我有这段代码:

procedure TMyService.ServiceStart(Sender: TService; var Started: Boolean);
begin
    try
    LogFile.Write('TTMyService.ServiceStart'); //This is my logging machine
    Started := True;
    InitializeService; //Sets some variables
    InitializeTimer; //Start a timer where all the magic happens
  except
     on e:Exception Do
      LogFile.Write('TTMyService.ServiceStart - ' + e.Message);
   end;
end;

这不记录任何内容,甚至不是“TMyService.ServiceStart”。我有一个想法,但它也不起作用,是取代TApplication VCL类。我将“Vcl.SvcMgr”文件的所有内容复制到一个新文件中,像这样修改它(我只添加了LogFile.Write Stuff):

procedure TServiceApplication.Run;
var
  ServiceStartTable: TServiceTableEntryArray;
  ServiceCount, i, J: Integer;
  StartThread: TServiceStartThread;
begin
{$IF NOT DEFINED(CLR)}
  AddExitProc(DoneServiceApplication);
{$ENDIF}
  if FindSwitch('INSTALL') then
    RegisterServices(True, FindSwitch('SILENT'))
  else if FindSwitch('UNINSTALL') then
    RegisterServices(False, FindSwitch('SILENT'))
  else
  begin
    Vcl.Forms.Application.OnException := OnExceptionHandler;
    ServiceCount := 0;
    for i := 0 to ComponentCount - 1 do
      if Components[i] is TService then Inc(ServiceCount);
    SetLength(ServiceStartTable, ServiceCount + 1);
{$IF NOT DEFINED(CLR)}
    FillChar(ServiceStartTable[0], SizeOf(TServiceTableEntry) * (ServiceCount + 1), 0);
{$ENDIF}
    J := 0;
    for i := 0 to ComponentCount - 1 do
      if Components[i] is TService then
      begin
{$IF DEFINED(CLR)}
        ServiceStartTable[J].lpServiceName := Components[i].Name;
        ServiceStartTable[J].lpServiceProc := ServiceMainDelegate;
{$ELSE}
        ServiceStartTable[J].lpServiceName := PChar(Components[i].Name);
        ServiceStartTable[J].lpServiceProc := @ServiceMain;
{$ENDIF}
        Inc(J);
      end;
    StartThread := TServiceStartThread.Create(ServiceStartTable);
    try
      while not Vcl.Forms.Application.Terminated do
      try
        Vcl.Forms.Application.HandleMessage;
      except
        on E: Exception do
        begin
          LogFile.Write('TServiceApplication.Run - ' + e.Message);
          DoHandleException(E);
        end;
      end;
      Vcl.Forms.Application.Terminate;
{$IF DEFINED(CLR)}
      DoneServiceApplication;
{$ENDIF}
      if StartThread.ReturnValue <> 0 then
      begin
        LogFile.Write('TServiceApplication.Run - ' + SysErrorMessage(StartThread.ReturnValue));
        FEventLogger.LogMessage(SysErrorMessage(StartThread.ReturnValue));
      end;
    finally
      StartThread.Free;
    end;
  end;
end;

Sorry, I don't know how to mark my changes in bold or in red to make it easier for you to see them

这是有效的,现在我可以得到一些“有用的”日志,但它也没有帮助。我明白了:

TServiceApplication.Run - The parameter is incorrect

而且我的机器(它仍在工作的地方)的服务将不复存在。到目前为止,我肯定知道15台机器无法正常工作,我无法在其他65机器上试用。不知何故,在我的机器中,我正在开发服务,如果我评论“Tapplication”它仍然有效“ 变化。

我遇到的另一个问题是,我不能在它破坏的机器上进行尽可能多的测试,因为它们被其他人使用,我要求他们做的每一次测试都会停止工作...

在我忘记之前,不知道它是否相关,但是为了获取修补程序的URL,该服务连接(在我的机器中)到IIS上托管的本地Web服务。

任何想法? 这够清楚了吗?有任何疑问,请问他们! :D我真的迷失了,这有很高的优先级:'(

提前致谢! 尼古拉斯·洛佩斯

新数据1:

在新测试中,重新安装其中一台机器中的服务,接缝以解决问题。但是,如果不知道问题的原因,那就没用了。

3 个答案:

答案 0 :(得分:1)

您的日志消息TServiceApplication.Run - The parameter is incorrect表示StartThread.ReturnValue为87(ERROR_INVALID_PARAMETER)。唯一可能发生的方法是StartServiceCtrlDispatcher()TServiceStartThread.Execute()调用时失败。 StartServiceCtrlDispatcher()只需要1个参数 - ServiceStartTable设置的TServiceApplication.Run()数组。该数组包含用于接收SCM消息的服务名称和Main()回调。所以这个数组有问题,你需要找出它是什么。它可能没有正确填充,或者在调用StartServiceCtrlDispatcher()之前被破坏。

要诊断问题,您必须使用IDE调试器逐步执行TService启动代码。这意味着使用调试器的附加到进程功能,因为IDE无法自动启动服务以进行调试。您必须首先向S​​CM发出一个启动,然后将调试器附加到生成的进程(单击附加对话框中的“显示系统进程”复选框)。这也意味着调整项目代码以使启动延迟,直到附加调试器。我通常在OnStart事件中通过在循环中调用IsDebuggerPresent()来处理它,但由于你的OnStart没有触发,你必须在启动逻辑中提前做延迟,例如就像TApplication开始初始化TService对象之前的主DPR一样。

到目前为止,在此讨论中,根本没有足够的信息可供此处的任何人为您诊断问题。

答案 1 :(得分:1)

我遇到了类似的问题:

  •   

    由于以下错误,XXX服务无法启动:   该服务未及时响应启动或控制请求。

  • 从未被解雇的TService.OnStartTService.OnExecute个事件。
  • 服务的可执行文件路径(services.msc - &gt;右键单击服务 - &gt;属性)设置如下: C:\test\TrucServer.exe /startedbyscm:A357F915-40E33CD5-trucServer

=&GT;解决方案是重新安装服务(卸载sc.exe delete "Truc Server",然后安装C:\test\TrucServer.exe -install)。服务的可执行文件路径现在设置如下:C:\test\TrucServer.exe并且服务正常启动。

我没有尝试在TServiceApplication类中插入日志,但是您的错误消息:TServiceApplication.Run - The parameter is incorrect似乎确认我的解决方案可能与您的问题相对应,因为在我的情况下,/startedbyscm:A357F915-40E33CD5-trucServer参数似乎是罪魁祸首

我没有尝试跟踪Vcl.SvcMgr中的错误消息。

答案 2 :(得分:0)

就我而言,问题是TServiceDesc.displayName。我尝试/install/uninstall并在卸载时无法找到该名称。因为在/uninstall上找不到它,所以服务器管理器找不到它已经启动。所以&#34;服务&#34;总是&#34;开始&#34;。为什么有些名字还可以,有些名字不能说明。没什么特别的。

DisplayName := "Name DB Service";

它不起作用。所以我让exedisplayName完全相同。不确定这是怎么发生的,但错误的原因是服务形式的名称,可执行文件的名称和DisplayName。所有这三个人在某种程度上混在一起。