繁体   English   中英

是否可以安装同一个 delphi 服务应用程序的多个实例?

[英]Is it possible to install multiple instances of the same delphi service application?

我有一个内置于 Delphi 的服务应用程序,效果很好。 它完全符合我的要求,一切都很开心。 一切都很好,直到我想在一台机器上运行该服务的两个(或更多)实例。 由于服务名称是硬编码到程序中的(通过服务的 Name 属性),我只能在任何给定的计算机上安装该服务一次。 如果我尝试在运行时修改 Name 属性,则服务不会响应,除非 Name 属性设置为与设计时设置的相同。

我已经为此做了一个解决方法,我将所有不直接与服务控制管理器交互的代码封装到单独的单元中。 然后,我为每个我想要的服务实例编写一个单独的 Delphi 项目,该服务具有足够的代码来启动自身并开始运行主代码。

在我看来,这种方法很丑陋,而且肯定效率低下。 它适用于两个实例,但是我们需要第三个和第四个,然后......

有什么方法可以修改我的代码,以便我只有一个 Delphi 项目,它可以通过一些简单的运行时输入(例如命令行标志)作为多个服务实例安装和运行自身?

或者可能是一个更广泛的问题:是否有实现目标的“正确方法”?

您还没有明确说明您在 TService 子类中尝试更改的内容。

您是否添加了“BeforeInstall”处理程序?

就像是:

procedure TServiceMain.ServiceLoadInfo(Sender : TObject);// new method, not an override
begin
  Name := ParamStr(2);
  DisplayName := ParamStr(3);
end;

procedure TServiceMain.ServiceBeforeInstall(Sender: TService);
begin
  ServiceLoadInfo(Self);
end;
procedure TServiceMain.ServiceCreate(Sender: TObject);
begin
  ServiceLoadInfo(Self);
end;

如果您定期执行此操作,则将 TService 子类化以在构造函数中执行此操作。

您也应该在 BeforeUninstall 中执行相同的操作 - 将两个事件指向相同的方法。

C:\>servicename /install MyService "My Service Description"

您可以在内部创建具有多个线程的服务,每个线程都像它自己的服务版本/副本一样。 您可以使用服务 Controller API, IIRC 来控制它。

是的,可以安装同一服务的多个实例,您只需要在安装时(而不是运行时)动态更改名称,但这并不理想。 (代码项目http://www.codeproject.com/KB/dotnet/MultipleInstNetWinService.aspx上有一些示例代码)

但是,我倾向于重新考虑您的方法,服务流程本身实际上是 singleton,如果您需要运行流程的多个实例,也许您的服务应该只控制和管理多个流程而不是流程。

上面接受的答案非常有帮助。

我使用的代码:

procedure TService1.ServiceAfterInstall(Sender: TService);
begin
//http://stackoverflow.com/questions/612587/is-it-possible-to-install-multiple-instances-of-the-same-delphi-service-applicati
//http://www.c-sharpcorner.com/UploadFile/timosten/DynamicServiceInCSharp11262005062503AM/DynamicServiceInCSharp.aspx?ArticleID=4d5020e4-7317-425c-ab29-5bf37a1db421
//http://support.microsoft.com/kb/137890
  SaveRegSetting('\SYSTEM\CurrentControlSet\Services\' + Name, 'ImagePath', ParamStr(0) + ' --name=' + Name, HKEY_LOCAL_MACHINE)
end;

procedure TService1.ServiceCreate(Sender: TObject);
begin
  Name := Trim(FCommandLineOptions.Values['name']);
  DisplayName := Name;
end;

SaveRegSetting 是我自己的过程,而 FCommandLineOptions 是一个 object,用于标记命令行参数。

为了破解注册表,我建议使用以下指南并使用 Windows 服务 Controller (sc.exe) 命令行界面:

使用 sc.exe 创建服务时如何传入上下文参数?

(编辑:请使用建议的代码来获取 Name & DisplayName 属性,只是不要使用 /install 开关为您的服务可执行文件安装您的服务。)

将所有代码包装到继承自 TThread 的 class 中。

当您的服务启动时,它将从设置文件或注册表中读取一个数字,并创建您的 class 的多个实例。

每个实例独立运行。

要更改运行实例的数量,您可以关闭服务,编辑设置(在文件或注册表中)并重新启动服务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM