Delphi 7在64位Server 2008上的问题

3

有没有人尝试过将Delphi附加到自己的Windows服务(32位应用程序)进程中,在Windows Server 2008 64位下运行?

当我尝试这样做时,我会收到以下错误消息: 无法创建进程。参数不正确。

如果你们中的任何人知道如何做到这一点,那么真的非常感谢你的帮助。

谢谢!


你尝试过将Delphi 7调试器附加到64位services.exe吗?如果是这样,它应该会失败!Delphi 7是一个32位进程,无法调试64位进程。 - Cosmin Prund
1
我在那个领域没有太多经验;但是我会从在我的用户帐户下运行服务开始,并编辑问题以明确我正在调试自己的32位服务,因为你称其为“windows服务”! - Cosmin Prund
虽然你可以调试Delphi服务,但是你需要跳过一些麻烦的步骤才能使其正常工作。我从不费心,只需确保我的服务可以作为服务或标准应用程序运行。当我想要调试时,我以标准应用程序的方式运行,从而避免所有的麻烦。这种方法的主要好处之一是启动代码可以轻松地进行调试。 - David Heffernan
@David:我想知道的是,你是如何不仅直接从约翰的脑海中读取问题,而且还在约翰发布问题的同时发布答案的。这需要多少练习? :) - Andriy M
@Andriy 那是我的错误(评论被删除后又重新发布了):) 我只是在玩“stackoverflow”,试图弄清楚为什么有些评论中当我写“@author”时它是可见的,有时它不是...无论如何,我还没有找到答案... - John
显示剩余6条评论
2个回答

10

虽然你可以调试 Delphi 服务,但你需要通过一些麻烦的步骤才能使其正常工作。我从不费心,只需确保我的服务可以作为服务或标准应用程序运行。当我想调试时,我作为标准应用程序运行,从而避开所有麻烦。

为了回答这个问题,我已将所有代码剪切到一个文件中,但你要以不同的方式组织代码。

program MyService;

uses
  SysUtils, Classes, Windows, Forms, SvcMgr;

type
  TMyService = class(TService)
  private
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServicePause(Sender: TService; var Paused: Boolean);
    procedure ServiceExecute(Sender: TService);
    procedure ServiceContinue(Sender: TService; var Continued: Boolean);
  protected
    FDescription: string;
    FEventLogSourceName: string;
    procedure Initialise; virtual; abstract;
    class function CreateRunner: TObject; virtual; abstract;
  public
    constructor Create(AOwner: TComponent); override;
    function GetServiceController: TServiceController; override;
  end;
  TMyServiceClass = class of TMyService;

{ TMyService }

constructor TMyService.Create(AOwner: TComponent);
begin
  inherited;
  Initialise;
  OnStart := ServiceStart;
  OnStop := ServiceStop;
  OnPause := ServicePause;
  OnExecute := ServiceExecute;
  OnContinue := ServiceContinue;
end;

procedure TMyService.ServiceStart(Sender: TService; var Started: Boolean);
begin
  Started := True;
end;

procedure TMyService.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  Stopped := True;
end;

procedure TMyService.ServiceContinue(Sender: TService; var Continued: Boolean);
begin
  ServiceStart(Sender, Continued);
end;

procedure TMyService.ServicePause(Sender: TService; var Paused: Boolean);
begin
  ServiceStop(Sender, Paused);
end;

procedure TMyService.ServiceExecute(Sender: TService);
var
  Runner: TObject;
begin
  Runner := CreateRunner;
  Try
    while not Terminated do begin
      ServiceThread.ProcessRequests(True);
    end;
  Finally
    FreeAndNil(Runner);
  End;
end;

var
  Service: TMyService;

procedure ServiceController(CtrlCode: DWORD); stdcall;
begin
  Service.Controller(CtrlCode);
end;

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

procedure RunAsService(ServiceClass: TMyServiceClass; var Service);
var
  Application: TServiceApplication;
begin
  Application := SvcMgr.Application;
  Application.Initialize;
  Application.CreateForm(ServiceClass, Service);
  Application.Run;
end;

procedure RunAsStandardExecutable(ServiceClass: TMyServiceClass);
var
  Application: TApplication;
  Runner: TObject;
begin
  Application := Forms.Application;
  Application.Initialize;
  Runner := ServiceClass.CreateRunner;
  Try
    while True do begin
      Try
        Application.HandleMessage;
      Except
        Application.HandleException(Application);
      End;
    end;
  Finally
    FreeAndNil(Runner);
  End;
end;

procedure ServiceMain(ServiceClass: TMyServiceClass);
begin
  if FindCmdLineSwitch('RunAsApp', ['-', '/'], True) then begin
    RunAsStandardExecutable(ServiceClass);
  end else begin
    RunAsService(ServiceClass, Service);
  end;
end;

begin
  ServiceMain(TMyService);
end.
为了使用这个功能,你需要创建一个新的类,继承自 TMyService ,并实现 InitialiseCreateRunner 方法。其中 CreateRunner 是关键。在我的服务中,这会创建一个对象,该对象打开一个监听套接字,以便客户端可以进行通信。
标准应用程序代码非常基础。它甚至没有终止机制 - 它在一个 while True 循环中运行。这对于我的调试需求没有影响。

谢谢,我已采用了你的代码。非常感谢,也感谢能够直接从我的头脑中读取 :) - John
@John 不客气。我们的目标是在 Stack Overflow 提供全方位的服务!;-) - David Heffernan
这样做的好处是您不会在实际环境中调试服务,也不会使用服务将运行的正确用户。我从未遇到过连接和调试服务的问题,即使在64位操作系统下也是如此。 - user160694
@Idsandon,你提出了一个非常有价值的观点。这完全取决于你在调试器中寻找什么。我所做的很多服务调试都涉及到服务的主要功能以及它如何与客户端进行交互。我的方法效果很好。如果你遇到了与权限、会话、桌面等相关的问题,那么我同意现场调试是你想要的。 - David Heffernan

1
你尝试以管理员身份运行IDE了吗?
我在Win64下已经执行了这样的过程,但是据我记得必须以管理员权限运行IDE。

是的,错误是一样的。我也尝试更改 Delphi IDE 的兼容性级别,但仍然出现相同的错误。 - John
您是否在SYSTEM帐户下运行服务? - Warren P
@Warren服务在系统下进行了测试,也在我登录的帐户下进行了测试。但是这些都没有起作用... - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接