debugging 如何用 Delphi 调试Windows服务?

g0czyy6m  于 2023-10-24  发布在  Windows
关注(0)|答案(7)|浏览(175)

有没有一种方法可以用 Delphi 完全调试Windows服务?

ryoqjall

ryoqjall1#

实际上这很简单,只要使用标准的DEBUG编译器指令将服务作为控制台应用程序而不是服务启动即可。

program MyServiceApp;

{$ifdef DEBUG}
  {$APPTYPE CONSOLE}
{$endif}

uses
  System.SysUtils,

[..]

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.
hrirmatl

hrirmatl2#

您可以从Colin Wilson's NT Low Level Utilities使用unitslogService.pas(页面已消失,available in the wayback machine
然后在DPR中:

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开关从命令行运行,和。

fumotvh3

fumotvh33#

使用Run -> Attach to process.这样你就可以调试一个服务,而不需要对它的代码做任何修改。唯一棘手的部分可能是调试服务的启动代码,因为附加可能需要一些时间,而启动必须在30秒内发生。(尽管你可以调整Windows以允许更长的时间)。(sleep.)以允许您及时附加,或者如果您只是需要查看发生了什么,您可以使用OutputString()打印到调试输出(使用 Delphi Event View查看)。

brqmpdu1

brqmpdu14#

有:Debugging services: an easy way
你用 Delphi 创建服务吗?那么也许你也对每次启动、重新启动、杀死和附加到服务流程应用程序的耗时方式感到恼火。好吧,有补救措施。
您不需要这样做,而是将 Delphi 作为一个SYSTEM应用程序运行,并对服务代码做一些小的修改。

zbsbpyhn

zbsbpyhn5#

我试过这个,但只出现了汇编代码的cpu窗口。
那么你只需要解决这个问题。
基本上,要调试Win 2服务,有几种方法:

  • 使用“附加到进程”命令将调试器附加到已运行的服务。如果需要在一开始就附加调试器,则可以插入启动延迟以便有时间附加调试器。但是,您还必须调整系统以增加服务超时。
  • 使用"Image File Execution Options" registry key在服务启动时强制运行 Delphi 的调试器。关于系统超时的考虑同样适用。
  • 将服务临时转换为正常的应用程序,并在调试器下正常运行。您可以在不同的用户帐户下重新启动IDE,以获得更多的“服务”特权。

如果由于某种原因,在开始调试后,您的服务只有CPU视图-这意味着 Delphi 的调试器无法找到服务的调试信息。这是另一个问题,您应该寻找解决方案。
通常,你需要做:
1.确保您的服务应用程序的输出文件夹设置为系统将从中加载的文件夹。即,如果您的服务位于C:\Windows\System32中,则将输出文件夹设置为C:\Windows\System32。不要将.exe文件从输出文件夹复制到其他地方。对于64系统,您可以尝试别名(sysnative/SysWOW 64)或真实的名称。我认为最好将输出路径设置为项目文件夹,并重新注册要从项目文件夹加载的服务。
1.(可选)将DCU的输出路径设置为与.exe文件相同的文件夹。
1.删除所有DCU文件。
1.确保在项目选项中的“调试器”页面上启用调试选项。
1.(可选)此外,您还可以在“链接器”页面上包含TD 32/RSM/MAP选项。
1.确保没有IDE expert/extension,这可能会修改.exe文件,调试信息或这些文件的文件修改日期。
1.确保其他位置没有旧文件(DCU/exe)。
1.进行完全重建(Project/Build all)。
1.运行服务。

kxkpmulp

kxkpmulp6#

是的。
在您的dpr中:

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.xml)来启动和停止服务。服务还应该有自己的线程(服务线程)来响应来自SCM或我们的服务控制线程的控制代码,以及一个或多个单独的线程来完成其实际工作。为实际工作单独的线程(而不是在TService后代的事件处理程序中对其进行编码),以确保TService本身运行的线程始终可以自由响应SCM的控制代码,并且即使工作线程被冻结,您仍然可以停止和启动服务。
这种方法也允许你调试服务应用程序的代码,但是需要相当多的代码,并在windows API函数中放置几个钩子来正常工作。太多了,不能在短时间内展示。也许有一天我会在一篇文章中写出来。
同时,如果你不想自己编写代码,你有两个选择。要么使用SVCOM这样的库,要么使用Mick提到的库,它们可以为你做所有的事情。或者当处于调试模式时,将服务代码一起绕过,并“简单地”将服务作为“普通”表单应用程序启动。事件处理程序,但出于上述原因,无论如何我都建议使用它。

ntjbwcob

ntjbwcob7#

需要知道的是,你可以轻松调试安装和卸载服务。
以管理员身份运行 Delphi ,在“运行/参数.”对话框中的“参数”设置中添加“/install”或“/uninstall”命令行参数,并通过调试运行服务应用程序。

相关问题