我在使用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:
在新测试中,重新安装其中一台机器中的服务,接缝以解决问题。但是,如果不知道问题的原因,那就没用了。
答案 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无法自动启动服务以进行调试。您必须首先向SCM发出一个启动,然后将调试器附加到生成的进程(单击附加对话框中的“显示系统进程”复选框)。这也意味着调整项目代码以使启动延迟,直到附加调试器。我通常在OnStart
事件中通过在循环中调用IsDebuggerPresent()
来处理它,但由于你的OnStart
没有触发,你必须在启动逻辑中提前做延迟,例如就像TApplication
开始初始化TService
对象之前的主DPR一样。
到目前为止,在此讨论中,根本没有足够的信息可供此处的任何人为您诊断问题。
答案 1 :(得分:1)
我遇到了类似的问题:
由于以下错误,XXX服务无法启动: 该服务未及时响应启动或控制请求。
TService.OnStart
或TService.OnExecute
个事件。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";
它不起作用。所以我让exe
和displayName
完全相同。不确定这是怎么发生的,但错误的原因是服务形式的名称,可执行文件的名称和DisplayName。所有这三个人在某种程度上混在一起。