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.
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.
7条答案
按热度按时间ryoqjall1#
实际上这很简单,只要使用标准的DEBUG编译器指令将服务作为控制台应用程序而不是服务启动即可。
[..]
hrirmatl2#
您可以从Colin Wilson's NT Low Level Utilities使用unitslogService.pas(页面已消失,available in the wayback machine)
然后在DPR中:
通过这种方式,您可以在 Delphi 中运行调试(通过设置项目调试器参数),将EXE用作服务,或使用
-DEBUG
开关从命令行运行,和。fumotvh33#
使用Run -> Attach to process.这样你就可以调试一个服务,而不需要对它的代码做任何修改。唯一棘手的部分可能是调试服务的启动代码,因为附加可能需要一些时间,而启动必须在30秒内发生。(尽管你可以调整Windows以允许更长的时间)。(sleep.)以允许您及时附加,或者如果您只是需要查看发生了什么,您可以使用OutputString()打印到调试输出(使用 Delphi Event View查看)。
brqmpdu14#
有:Debugging services: an easy way
你用 Delphi 创建服务吗?那么也许你也对每次启动、重新启动、杀死和附加到服务流程应用程序的耗时方式感到恼火。好吧,有补救措施。
您不需要这样做,而是将 Delphi 作为一个SYSTEM应用程序运行,并对服务代码做一些小的修改。
zbsbpyhn5#
我试过这个,但只出现了汇编代码的cpu窗口。
那么你只需要解决这个问题。
基本上,要调试Win 2服务,有几种方法:
如果由于某种原因,在开始调试后,您的服务只有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.运行服务。
kxkpmulp6#
是的。
在您的dpr中:
DebugService是一个过程,它创建一个调试表单,一个服务控制线程,并通过调用Forms.Application.Run启动所有内容。
您可以将服务控制线程与Windows的SCM进行比较(服务控制管理器),带有与SCM对话的应用程序的调试表单(如services.xml)来启动和停止服务。服务还应该有自己的线程(服务线程)来响应来自SCM或我们的服务控制线程的控制代码,以及一个或多个单独的线程来完成其实际工作。为实际工作单独的线程(而不是在TService后代的事件处理程序中对其进行编码),以确保TService本身运行的线程始终可以自由响应SCM的控制代码,并且即使工作线程被冻结,您仍然可以停止和启动服务。
这种方法也允许你调试服务应用程序的代码,但是需要相当多的代码,并在windows API函数中放置几个钩子来正常工作。太多了,不能在短时间内展示。也许有一天我会在一篇文章中写出来。
同时,如果你不想自己编写代码,你有两个选择。要么使用SVCOM这样的库,要么使用Mick提到的库,它们可以为你做所有的事情。或者当处于调试模式时,将服务代码一起绕过,并“简单地”将服务作为“普通”表单应用程序启动。事件处理程序,但出于上述原因,无论如何我都建议使用它。
ntjbwcob7#
需要知道的是,你可以轻松调试安装和卸载服务。
以管理员身份运行 Delphi ,在“运行/参数.”对话框中的“参数”设置中添加“/install”或“/uninstall”命令行参数,并通过调试运行服务应用程序。