Delphi Windows服务命令行参数

6
我有一个基于Delphi的Windows服务,在安装时解析一些命令行参数。我希望将这些参数添加到服务的命令行(注册表上的ImagePath值),以便始终使用它们启动服务。
如何实现?
我希望在注册表键HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\MyService下看到以下内容:
- ImagePath = C:\Path\to\my\service.exe -some -arguments
谢谢。
更新:安装是通过>MyService.exe /install -some -arguments完成的。我想要持久化这些参数到命令行中。
更新:我通过直接写入注册表找到了解决方案(请参见here),但我仍然希望有更优雅的解决方案,例如使用某些TService属性或类似的东西。谢谢!
6个回答

9

经过一番研究,我放弃了优雅的方法,选择了直接写入注册表的直截了当的路径。

为了简化事情,我将要传递的参数存储在我的TService变量中。然后,我将AfterInstall事件设置为使用TRegistry对象直接将我想要的确切命令行写入注册表。

uses Registry;
procedure MyService.AfterInstall(Sender: TObject) ;
var
  reg:TRegistry;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := 'HKEY_LOCAL_MACHINE';
    if reg.OpenKey('SYSTEM\CurrentControlSet\Services\MyService', True) then
    begin
      reg.WriteExtendString ('ImagePath', ParamStr(0) + ' -some -arguments') ;
      reg.CloseKey;
    end;
  finally
    reg.Free;
  end;
end;

虽然这不是我一开始想要的优雅解决方案,但它能胜任工作。

感谢其他答案提供的帮助!


5

可以将服务参数传递给CreateService函数中的lpBinaryPathName参数。在Delphi的TService中,这是在TServiceApplication.RegisterServices.InstallService中调用的,您无法轻松地覆盖它。

因此,我怀疑最简单的方法是处理TService.AfterInstall事件,并通过ChangeServiceConfig自己更新注册表。


3

我刚发现了一个小惊喜,可能值得分享。

您可以以下列至少一种方式指定Windows服务的参数:

  1. 在Service Manager GUI中键入"Startparameter"。
  2. 将其作为参数传递给:sc.exe YourService param1 param2
  3. 在注册表中输入条目ImagePath=..\YourService.exe param1 param2

在Delphi中,有两种方法来查询应用程序/服务参数:

  • System.ParamCount/System.ParamStr: 这种方式可以获取第3种方法的参数。
  • TService.ParamCount/TService.Param[]: 这种方式可以获取第1种和第2种方法的参数。

只有在从服务管理器启动服务时才能工作,它不会持久化。 - user160694
是的。我已经按照上面被接受的答案所描述的实现了参数持久化(在AfterInstall中)。这个答案只是额外提供的信息。 - nang

2

您应该使用SCM API来正确安装和配置服务。SC.EXE是SCM API的命令行界面。在这种情况下,您不应直接操作注册表,虽然它可以工作,但这也取决于服务帐户具有哪些权限。 无论如何,如果您将命令行参数嵌入代码中,我想知道为什么需要它们 - 通常这些参数是在服务外部(由安装程序、配置器或其他任何东西)设置的,以更改服务行为。


关于权限的好点子,我没有考虑到。关于我的需求,我的服务没有配置应用程序,安装是通过/install参数完成的(我猜这样,如果我有权限为服务创建注册表键,则我也有权限手动编辑该键)。这些提供的参数是我想要持久化的。我现在不太记得为什么了,但我认为是因为我希望服务多次运行,具有不同的参数。 - Pablo Venturino
如果我有权限创建注册表键,则问题就在那里。Vista/7可能不允许它,除非使用提升的特权进行操作。/install开关对于快速和脏的服务安装很方便,但最好为用户提供适当的安装/卸载过程。我编写了一个脚本,可用于免费的InnoSetup安装工具来处理服务(http://www.sandon.it/?q=node/9),其他安装程序原生支持服务。 - user160694

0
Pablo, 我有同样的问题,找不到任何东西,也尝试了编辑注册表的方法。 此外,我还使用自定义操作来创建额外的安装目录并复制文件(使用C#)。 你的建议很有帮助,我也停止寻找“优雅”的方法。 谢谢。

0

我认为你不能让服务与它们一起启动,但如果你将这些参数存储在注册表中,你可以修改程序,在未来的启动中始终去获取它们。(即如果ParamCount = 0,则从注册表中检索参数)


你肯定可以使用这些参数启动服务。问题是如何让安装程序将它们添加到注册表中。 - Uwe Raabe

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