【问题标题】:How to remote debug a windows services with Delphi 10.2如何使用 Delphi 10.2 远程调试 Windows 服务
【发布时间】:2018-09-21 20:39:29
【问题描述】:

我熟悉使用附加进程功能调试用 Delphi 编写的 windows 服务。如果该服务与 Delphi IDE 在同一台服务器上运行,这将非常有效。

但是当涉及到远程调试服务时(即它在远程服务器上运行)它不再起作用:附加进程根本不显示服务进程。起初我以为是权限问题,但由于我可以看到其他用户进程但看不到服务进程,我相信不是。

我注意到,如果我在安装模式下运行服务(例如 /install),它会显示在进程列表中,我什至可以调试它。但如果它作为 SCM 的常规 Windows 服务运行,我就不能。

这是已知限制还是远程调试设置有问题?如果这是一个限制,是否有实际的解决方法?

【问题讨论】:

  • 您是否以管理员身份在远程计算机上运行远程调试器?
  • 允许您的服务作为无 UI 的桌面进程交替运行以使调试更容易,这通常是明智的。显然,如果您需要调试仅作为会话 0 服务运行的方面。
  • 远程调试器以管理员权限运行,可以看到其他用户进程,但看不到服务进程。
  • 我看到了有关使用编译器指令(例如 $IFDEF DEBUG)构建控制台应用程序/桌面应用程序而不是服务应用程序以进行调试的建议。但在这种情况下,我没有测试在现实生活中运行的完全相同的应用程序,因此可能不会重现相同的问题。我相信我是在改写 David 的意思。

标签: delphi remote-debugging


【解决方案1】:

面临同样的问题。

我编写了一个代表 LOCAL_SYSTEM 运行 PAServer 的服务。 IDE 中立即出现了所有进程。

unit UrsPASImpl;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Vcl.SvcMgr;

type
  TPAServerLauncher = class(TService)
    procedure ServiceStart(Sender: TService; var AStarted: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
    FProcHandle: THandle;
    FInWritePipe: THandle;
  public
    function GetServiceController: TServiceController; override;
  end;

var
  PAServerLauncher: TPAServerLauncher;

implementation

uses
  Winapi.Windows,
  System.SysUtils;

{$R *.dfm}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  PAServerLauncher.Controller(CtrlCode);
end;

function TPAServerLauncher.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TPAServerLauncher.ServiceStart(Sender: TService;
  var AStarted: Boolean);
var
  LBasePath: string;
  LProcName: string;
  LInReadPipe: THandle;
  LSecAttr: TSecurityAttributes;
  LStartup: TStartupInfo;
  LProcInfo: TProcessInformation;
begin
  try
    LBasePath := ExtractFilePath(GetModuleName(HInstance));
    LProcName := LBasePath + 'PAServer.exe';

    LSecAttr.nLength := SizeOf(LSecAttr);
    LSecAttr.lpSecurityDescriptor := nil;
    LSecAttr.bInheritHandle := True;

    Win32Check(CreatePipe(LInReadPipe, FInWritePipe, @LSecAttr, 0));
    try
      Win32Check(SetHandleInformation(FInWritePipe, HANDLE_FLAG_INHERIT, 0));

      FillChar(LStartup, SizeOf(LStartup), 0);
      LStartup.cb := SizeOf(LStartup);
      LStartup.dwFlags := STARTF_USESTDHANDLES;
      LStartup.hStdInput := LInReadPipe;

      Win32Check(CreateProcess(
        PChar(LProcName),
        PChar(Format('"%s"', [LProcName])),
        nil,
        nil,
        True,
        0,
        nil,
        PChar(LBasePath),
        LStartup,
        LProcInfo
      ));
    finally
      CloseHandle(LInReadPipe);
    end;
    CloseHandle(LProcInfo.hThread);

    FProcHandle := LProcInfo.hProcess;
    AStarted := True;
  except
    on E: Exception do begin
      LogMessage(E.Message);
      AStarted := False;
      if FInWritePipe <> 0 then begin
        CloseHandle(FInWritePipe);
        FInWritePipe := 0;
      end;
    end;
  end;
end;

procedure TPAServerLauncher.ServiceStop(Sender: TService; var Stopped: Boolean);
const
  CExit: AnsiString = 'q' + sLineBreak;
var
  LWriteCnt: Cardinal;
begin
  if WaitForSingleObject(FProcHandle, 0) = WAIT_TIMEOUT then begin
    Win32Check(WriteFile(FInWritePipe, CExit[1], Length(CExit), LWriteCnt, nil));
    WaitForSingleObject(FProcHandle, INFINITE);
  end;
  CloseHandle(FProcHandle);
  CloseHandle(FInWritePipe);
end;

end.

GitHub 项目https://github.com/anton-shchyrov/PAServerLauncher

【讨论】:

  • 嗨,Anton,对我来说,你的启动器不起作用——或者我至少不知道如何让它起作用。是否需要进行任何特定配置才能使其正常工作?至少当我启动您的服务时,我无法从 Delphi 11 连接到 PAServer。
  • @RolandKossow 1. 正常启动时可以连接PAServer吗? 2、启动服务后PAServer是否出现在进程中?
猜你喜欢
  • 2015-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2014-10-25
相关资源
最近更新 更多