有没有一种用Delphi完全调试Windows服务的方法?
有没有一种用Delphi完全调试Windows服务的方法?
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
开关从命令行运行。
其实很简单。只需使用标准的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.
使用运行 -> 附加进程。这样您可以在不对其代码进行任何更改的情况下调试服务。唯一棘手的部分可能是调试服务启动代码,因为附加可能需要一些时间,并且启动必须在30秒内发生(尽管您可以调整 Windows 以允许更长时间)。您可以使用延迟(睡眠...)来允许您及时附加,或者如果您只需要查看发生了什么,可以使用 OutputDebugString() 打印到调试输出(使用 Delphi 事件视图查看)。
有的。
在你的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.msc),以启动和停止服务。该服务还应具有自己的线程(服务线程),以响应来自SCM或我们的服务控制线程的控制代码以及一个或多个单独的线程来执行其实际工作。您需要为实际工作使用单独的线程(而不是在TService派生类的事件处理程序中编码),以确保TService本身运行的线程始终空闲以响应来自SCM的控制代码,并且即使工作线程被冻结,您仍然可以停止和启动服务。
这种方法也允许您调试服务应用程序代码,但涉及相当数量的代码和将一些钩子放入Windows API函数中才能正常工作。这里无法在短时间内展示太多。也许我会在某天写一篇文章来详细介绍。
与此同时,如果您不想全部自己编写代码,则有两个选择。要么使用诸如SVCOM或Mick提到的库等,它们可以为您完成所有工作;要么在调试模式下完全绕过服务代码,并将其“简单”地启动为“普通”窗体应用程序。您将需要从TService派生类的代码/事件处理程序中解开您服务的实际功能,但出于上述原因,我建议这样做。