如何使用Delphi调试windows服务?
有没有办法用Delphi完全调试windows服务?有,有: 您是否使用Delphi创建服务? 那么也许你也对这件事感到恼火 耗时的启动方式, 重新启动、终止并连接到 每个应用程序的服务流程 时间嗯,有补救办法 你不需要这样做。而是跑 Delphi作为一个系统的应用和做 对服务进行了一些小的调整 代码 有 在您的dpr中:如何使用Delphi调试windows服务?,delphi,debugging,windows-services,service,Delphi,Debugging,Windows Services,Service,有没有办法用Delphi完全调试windows服务?有,有: 您是否使用Delphi创建服务? 那么也许你也对这件事感到恼火 耗时的启动方式, 重新启动、终止并连接到 每个应用程序的服务流程 时间嗯,有补救办法 你不需要这样做。而是跑 Delphi作为一个系统的应用和做 对服务进行了一些小的调整 代码 有 在您的dpr中: Application.CreateForm(TMyService, MyService); _ServiceInDebugMode := SysUtils.FindCm
Application.CreateForm(TMyService, MyService);
_ServiceInDebugMode := SysUtils.FindCmdLineSwitch('DEBUG', True);
if _ServiceInDebugMode then
DebugService(MyService)
else
SvcMgr.Application.Run;
DebugService是一个创建调试窗体、服务控制线程并通过调用Forms.Application.Run启动一切的过程
您可以将服务控制线程与Windows的SCM(服务控制管理器)进行比较,将调试窗体与与与SCM(如services.msc)对话以启动和停止服务的应用程序进行比较。服务还应该有自己的线程(服务线程)来响应来自SCM或我们的服务控制线程的控制代码,并有一个或多个单独的线程来执行其实际工作。您需要为实际工作使用单独的线程(而不是在TService子代的事件处理程序中对其进行编码),以确保TService本身运行的线程始终可以自由响应SCM的控制代码,并且即使在每个工作线程冻结时,您仍然可以停止和启动服务
这种方法也允许您调试服务应用程序代码,但需要相当多的代码,并在windows api函数中放置几个钩子才能正常工作。太多了,不能在短时间内展示。也许有一天我会把它写在一篇文章里
同时,如果你不想自己编写代码,你有两个选择。可以使用SVCOM或Mick提到的库,它们可以为您完成所有工作,或者在调试模式下,将服务代码全部传递到一起,并“简单地”作为“普通”表单应用程序启动您的服务。您必须将服务的真正功能与TService子代的代码/事件处理程序分离开来,但出于上述原因,我还是建议您这样做。您可以使用unitDebugService.pas from(页面已消失,) 然后在朝鲜:
begin
if (paramCount > 0) and (SameText(ParamStr(1), '-DEBUG')) then
begin
FreeAndNil (Application);
Application := TDebugServiceApplication.Create(nil);
end;
//... the rest of the normal DPR code
end.
通过这种方式,您可以在Delphi中通过调试运行(通过设置项目调试器参数),将EXE用作服务,或者使用
-DEBUG
开关从命令行运行,以及使用运行->附加到进程。通过这种方式,您可以调试服务,而无需对其代码进行任何更改。唯一棘手的部分可能是调试服务启动代码,因为连接可能需要一些时间,并且启动必须在30秒内完成(尽管您可以调整窗口以允许更长的时间)。您可以使用延迟(sleep…)来及时附加,或者如果您只需要查看发生了什么,可以使用OutputDebugString()打印到调试输出(使用Delphi事件视图查看)
我已经试过了,但只在cpu窗口中显示汇编代码 那么你只需要解决这个问题 基本上,要调试Win2服务,有几种方法:
- 使用“附加到进程”命令将调试器附加到已经运行的服务。如果一开始就需要附加调试器,可以插入启动延迟以有时间附加调试器。但是,您还必须调整系统以增加服务超时
- 用于在服务启动时强制运行Delphi的调试器。关于系统超时的考虑同样适用
- 将服务临时转换为常用应用程序,并在调试器下正常运行。您可以在不同的用户帐户下重新启动IDE,以获得“服务”的更多特权
其实很简单。只需使用标准的DEBUG编译器指令作为控制台应用程序而不是服务启动服务
program MyServiceApp;
{$ifdef DEBUG}
{$APPTYPE CONSOLE}
{$endif}
uses
System.SysUtils,
[……]
RunAsSys听起来不错。您链接的文章中的示例代码使用条件定义来选择“模式”。你知道RunAsSys是否允许选择调试模式而不必重新构建应用程序吗?Ie使用命令行参数进入调试模式,而不是作为服务运行?我不确定,但您似乎可以自己将该功能添加到其中。链接不再工作。我尝试过此操作,但仅显示带有汇编代码的cpu窗口。
附加到进程
工作正常。当调试器第一次连接到服务进程时,确实会出现CPU窗口,但您可以简单地将其关闭,然后按F9或Run按钮继续正常执行服务,然后
begin
{$ifdef DEBUG}
try
// In debug mode the server acts as a console application.
WriteLn('MyServiceApp DEBUG mode. Press enter to exit.');
// Create the TService descendant manually.
ServerContainer1 := TServerContainer.Create(nil);
// Simulate service start.
ServerContainer1.ServiceStart(ServerContainer1, MyDummyBoolean);
// Keep the console box running (ServerContainer1 code runs in the background)
ReadLn;
// On exit, destroy the service object.
FreeAndNil(ServerContainer1);
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
WriteLn('Press enter to exit.');
ReadLn;
end;
end;
{$else}
// Run as a true windows service (release).
if not Application.DelayInitialize or Application.Installing then
Application.Initialize;
Application.CreateForm(TServerContainer, ServerContainer1);
Application.Run;
{$endif}
end.