Windows services 使用Inno安装程序在Windows(Vista/XP/7)上安装服务

Windows services 使用Inno安装程序在Windows(Vista/XP/7)上安装服务,windows-services,inno-setup,Windows Services,Inno Setup,安装应用程序时,我需要安装并运行服务(installer.exe是使用Inno Setup创建的) 我使用下面的代码 [Run] Filename:"{sys}\myservice.exe "; Parameters: "-install" 我不确定这是否正确 (我为提醒重新启动添加了代码,但我想知道是否可以在安装后立即运行该服务,而无需重新启动电脑。) 欢迎评论。使用Silvio Iacarino的Inno设置 使用sc.exe,它很简单,唯一的缺点是您可能必须截取和解析输出,以了解出了什么

安装应用程序时,我需要安装并运行服务(installer.exe是使用Inno Setup创建的)

我使用下面的代码

[Run]
Filename:"{sys}\myservice.exe "; Parameters: "-install"
我不确定这是否正确

(我为提醒重新启动添加了代码,但我想知道是否可以在安装后立即运行该服务,而无需重新启动电脑。)

欢迎评论。

使用Silvio Iacarino的Inno设置

  • 使用sc.exe,它很简单,唯一的缺点是您可能必须截取和解析输出,以了解出了什么问题,如果出了问题
  • 使用我的Inno设置。它是SCM API上的Pascal脚本包装器,允许您完全控制服务。使用起来有点复杂,但它允许进行完整的错误检查和处理。有一些高级功能设计用于在标准的Inno设置对话框中显示错误

  • 注意:不要在任何Windows系统文件夹中安装您的服务。它们应被视为Windows专用文件夹。除非您有非常非常好的理由在那里编写(即驱动程序),否则您不应该在那里安装软件。将其安装在应用程序文件夹中。

    除了公认的答案之外,我只想让人们更容易使用Luigi Sandon的服务库(非常感谢!)。下载脚本后,您需要在安装脚本中添加类似于以下内容的[Code]部分:

    [Code]
    // source: https://stackoverflow.com/a/5416744 
    #include "services_unicode.iss"
    
    const
      SERVICE_NAME = 'MyService';
      SERVICE_DISPLAY_NAME = 'MyService';
      SERVICE_EXE = 'MyService.exe';
    
    procedure CurStepChanged(CurStep: TSetupStep);
    begin
      Log('CurStepChanged(' + IntToStr(Ord(CurStep)) + ') called');
    
      if CurStep = ssInstall then begin
        if ServiceExists(SERVICE_NAME) then begin
          if SimpleQueryService(SERVICE_NAME) = SERVICE_RUNNING then begin
            SimpleStopService(SERVICE_NAME, True, False);
          end;
          SimpleDeleteService(SERVICE_NAME);
        end;
      end
      else if CurStep = ssPostInstall then begin
        SimpleCreateService(SERVICE_NAME, SERVICE_DISPLAY_NAME, ExpandConstant('{app}\' + SERVICE_EXE), SERVICE_AUTO_START, '', '', False, False);
        SimpleStartService(SERVICE_NAME, True, False);
      end;
    end;
    
    procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
    begin
      Log('CurUninstallStepChanged(' + IntToStr(Ord(CurUninstallStep)) + ') called');
    
      if CurUninstallStep = usUninstall then begin
        if ServiceExists(SERVICE_NAME) then begin
          if SimpleQueryService(SERVICE_NAME) = SERVICE_RUNNING then begin
            SimpleStopService(SERVICE_NAME, True, False);
          end;
          SimpleDeleteService(SERVICE_NAME);
        end;
      end;
    end;
    
    这不是防弹的,但应该可以处理绝大多数情况

    不幸的是,我不知道是否有办法在[code]部分使用
    {VarName}
    emit语法,这就是为什么我将服务名称等声明为常量以及文件顶部的
    #define
    。如果您想要的常量是[Setup]部分的设置之一,则答案非常有用,但由于您不能随意向该部分添加内容,因此这并不适用于您可能想要为其定义常量的所有内容

    如果要为服务设置说明,则服务库不支持该功能,但使用[Registry]部分很容易,例如:

    [Registry]
    ; set the service description
    Root: HKLM; Subkey: "System\CurrentControlSet\Services\{#ServiceName}"; ValueType: string; ValueName: "Description"; ValueData: "{#ServiceDescription}"; Flags: deletevalue uninsdeletekey
    

    最后,我可以确认这也适用于Windows 10。

    一项服务安装后可以立即运行,我一直都这样做。尽管在您的情况下,如果安装程序必须替换正在使用的文件,则可能需要重新启动。如果我记得,安装服务的建议不是使用服务的自安装,而是直接从安装程序写入所有注册表项。您应该使用SCM(服务控制管理器)API来安装服务,无法访问注册表。@David Heffernan:一件事是写入HKLM\Software,另一件事是写入HKLM\System。SCM API是一个定义良好且已发布的API。我知道写入注册表比使用API容易,但API IMHO是处理服务注册最安全的方法-我找不到任何使用该API不能做的事情,并且需要直接进行注册表操作。什么是“特定于服务的设置”?如果它们不是Windows服务设置,而是特定于应用程序的代码设置,则应在HKLM\软件下编写,而不是在HKLM\系统下编写。当然,SCM不能处理特定于应用程序的设置。无论如何,并非所有服务都需要以LocalSystem权限启动(如果可能的话,也不应该),因此访问注册表的需要应该仔细评估,并正确设置。但是如果您使用的是Unicode版本的Inno setup,那么这些脚本将无法工作。请参阅@ldsandon的答案,并注意他“服务库”页面底部的链接。+1尼斯库,我将用以下内容替换我自己开发的函数服务:)+1很棒的库(不仅仅是尼斯库)。到目前为止,在Unicode版本中没有发现任何问题
    [Registry]
    ; set the service description
    Root: HKLM; Subkey: "System\CurrentControlSet\Services\{#ServiceName}"; ValueType: string; ValueName: "Description"; ValueData: "{#ServiceDescription}"; Flags: deletevalue uninsdeletekey