有没有办法用Delphi完全调试Windows服务?
答案 0 :(得分:26)
您可以使用 Colin Wilson's NT Low Level Utilities 中的unitDebugService.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
开关从命令行运行,并且。
答案 1 :(得分:18)
实际上很容易。只需使用标准的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.
答案 2 :(得分:14)
使用Run - >附加到流程。这样,您可以调试服务,而无需对其代码进行任何更改。唯一棘手的部分可能是调试服务启动代码,因为附加可能需要一些时间,并且启动必须在30秒内完成(尽管您可以调整Windows以允许更长的时间)。您可以使用延迟(睡眠...)来允许您及时附加,或者如果您只是需要查看会发生什么,您可以使用OutputDebugString()打印到调试输出(使用Delphi事件视图查看它)。
答案 3 :(得分:6)
是的,有: Debugging services: an easy way
您是否使用Delphi创建服务? 那么也许你也对此感到恼火 耗时的开始方式, 重启,杀戮和附加 每个服务流程应用程序 时间。好吧,有补救措施。
您不需要这样做。而是跑 Delphi作为SYSTEM应用程序而且做到了 一些小的适应服务 代码。
答案 4 :(得分:5)
我试过这个,但只出现带有汇编代码的cpu窗口。
那你只能解决这个问题。
基本上,要调试Win2服务,有几种方法:
如果由于某种原因在开始调试后只有您的服务的CPU视图 - 这意味着Delphi的调试器无法找到您的服务的调试信息。这是一个不同的问题,您应该搜索解决方案。
通常,您需要这样做:
答案 5 :(得分:3)
是的。
在你的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的控制代码,您仍然可以停止并且即使每次机会a /工作线程被冻结,也要启动服务。
这种方法也允许您调试服务应用程序代码,但涉及大量代码并将一些挂钩放入windows api函数中以正常工作。在短时间内显示太多。也许我有一天会在一篇文章中写下来。
与此同时,如果您不想自己编码,您有两种选择。要么使用像SVCOM这样的库,要么使用Mick提到的库来为您完成所有这些工作,或者在调试模式下将服务代码全部一起通过并“简单地”将您的服务作为“普通”表单应用程序启动。您必须从TService后代的代码/事件处理程序中解开服务的实际功能,但出于上述原因,这是我建议的。