Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以安装同一delphi服务应用程序的多个实例?_Delphi_Windows Services - Fatal编程技术网

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

是否可以安装同一delphi服务应用程序的多个实例?,delphi,windows-services,Delphi,Windows Services,我有一个在Delphi中构建的服务应用程序,效果非常好。它做的正是我想要它做的,一切都很快乐。在我想在一台机器上运行该服务的两个(或更多)实例之前,一切都很好。由于服务名称是硬编码到程序中的(通过服务的name属性),因此我只能在任何给定的计算机上安装一次服务。如果我试图在运行时修改Name属性,则除非Name属性设置为与设计时设置的相同的内容,否则服务不会响应 我已经为此做了一个变通方法,将所有不直接与服务控制管理器交互的代码封装到单独的单元中。然后,我为我想要的每个服务实例编写一个单独的De

我有一个在Delphi中构建的服务应用程序,效果非常好。它做的正是我想要它做的,一切都很快乐。在我想在一台机器上运行该服务的两个(或更多)实例之前,一切都很好。由于服务名称是硬编码到程序中的(通过服务的name属性),因此我只能在任何给定的计算机上安装一次服务。如果我试图在运行时修改Name属性,则除非Name属性设置为与设计时设置的相同的内容,否则服务不会响应

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

在我看来,这种方法是丑陋的,而且肯定是低效的。在两种情况下都可以,但是我们需要第三种和第四种,并且

是否有任何方法可以修改我的代码,使我只有一个Delphi项目,可以通过一些简单的运行时输入(例如,命令行标志)将自己作为多个服务实例安装和运行


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

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

是的,可以安装同一服务的多个实例,您只需在安装时(而不是运行时)动态更改名称,但这并不意味着需要更改名称。(代码项目中有一些示例代码)


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

您还没有明确说明您试图在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"

将所有代码包装到从TThread继承的类中

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

每个实例都独立运行


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

上面接受的答案非常有用

我使用的代码:

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是一个标记命令行参数的对象。

我建议使用以下指南并使用Windows服务控制器(sc.exe)命令行界面,而不是侵入注册表:


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

谢谢,但我不确定这是否适用于Delphi。这就是我试图做的——在安装事件期间更改displayName——但当服务试图以“错误”的名称启动时,它却被阻塞了。另外,请参阅我对Ken答案的评论。。。当Windows已经可以为我做控制器部分时,我自己做多线程控制器不是不必要的吗?@Mick:你是说Ken的建议是糟糕的设计,还是我想做的通常是糟糕的设计?为什么?我想了想,但它似乎基本上是在创建重复的代码。windows的服务功能已经内置了线程控制代码。为什么不利用这一点,而不是自己滚动?不,我不是这么说的。Windows具有服务控制器代码,可用于启动/停止多个线程。将服务代码移动到一个TThread中,对于服务的每个实例,只需启动另一个线程。我希望能更好地解释我的意图。对不起,我还是不明白。这在服务控制面板中是如何显示的(一个条目/多个条目)?您是建议我在代码中使用服务控制API(如call ControlService)还是只处理事件(如ServiceStart等)?它将显示为一个条目,因为只有一个显示名称。您需要响应ServiceStart以启动第一个线程,并使用服务控制API使第一个线程在运行后启动/停止各个线程。然后我是否可以停止线程2,让线程3和线程1继续运行(不编写大量代码来有效地重新创建服务控制器)?根据我的建议,是的。主线程将处理启动和停止子线程的请求;这些子线程将是执行实际工作的线程。您将使用服务控制API与服务的主线程通信。(正如我在回答下面对您的评论中提到的)如果我这样做,那么服务不会运行,除非ParamStr(2)等于IDE中对象检查器中为Name设置的值。如果ParamStr(2)不同,那么当服务启动时,它将进入一个永久的“启动”状态,并且永远不会执行。对不起,这只是需要的一部分。您还需要OnStart事件来调用它。(在这里使用内存!)我找不到您正在使用的ServiceLoadInfo方法。这是一个标准方法,还是仅仅是一个建议,即编写一个方法,以确定在中调用它的名称