使用Windows服务更新软件包会重置服务的帐户和密码

时间:2014-11-18 02:09:21

标签: wix

我正在使用WiX处理MSI安装程序。我试图尽可能简化开发:这是一个内部产品,我的用户就是我们的IT人员。

该产品包含一项Windows服务,必须配置为在每台计算机的不同帐户下运行。

我为用户规划的工作流程(首次安装)如下:

  1. 运行安装程序 (安装程序在默认帐户下设置服务)
  2. 通过sc或本地服务小程序停止服务
  3. 更新服务属性以在正确的计算机专用帐户下运行。 (每台计算机的帐户不同,只有IT人员才能访问密码。)
  4. 重新启动服务
  5. 后续更新将包括从更新的MSI文件安装。

    测试"小"更新,我很惊讶地发现安装程序将服务重置为在默认帐户下运行。这对我来说是一个主要问题,因为它使我的用户很难更新他们的服务器。每次有更新时,他们都必须在每台机器上重新输入帐户信息。我预计这会发生在" major"更新,但不是在"小"之一。

    1. 是否有办法配置安装程序,以便在" small"期间不会更改服务的现有帐户/密码配置。或者是"未成年人"更新吗

    2. 这会在"修复过程中发生吗? (我还没试过)?

    3. 这是我的组件在.wxs文件中的样子:

      <Component Id="cmpService" Guid="{MYGUIDHERE}">
        <File Id="filService" KeyPath="yes" Name="ServiceApp.exe" />
        <ServiceInstall Id="ServiceInstall" Name="ServiceApp" DisplayName="My Service"
                        Type="ownProcess" Start="auto" ErrorControl="normal"
                        Account="LocalSystem">
          <util:PermissionEx ... attributes here... />
        </ServiceInstall>
        <ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall"
                        Name="ServiceApp" Wait="yes" />
      </Component>
      

      如果没有任何更改,我原本预计Remove="uninstall"会保留服务。显然不是。 (如果这发生在&#34;主要&#34;更新),我不会太担心。

      我还注意到ServiceConfig元素的属性(OnReinstall)似乎符合条件,但根据蜡烛错误消息,OnReinstall非常清楚旨在仅影响元素(PreShutdownDelay等)的配置成员,而不是整个服务安装。

      我已经研究过这些:

      奇怪的是,this answer表明这仅仅是针对&#34; major&#34;升级。那不是我的经历。我的经历是侥幸吗?

      在安装过程中提示输入帐户和密码会很好,但是在这种情况下将密码存储在注册表或其他地方并不是一个真正的选择,并且必须在每次更新时重新输入凭据就像破坏性一样必须手动重新配置服务。

2 个答案:

答案 0 :(得分:0)

我今天与FireGiant进行了有关此确切问题的咨询电话,我们找到了解决方案。

背景故事:

  • 我们的应用程序安装MSI最初使用LocalService安装Windows服务,但是我们的实际桌面软件将此更改为NetworkService或什至在某些网络环境中可能需要的自定义用户帐户。
  • 我们的<Component> <ServiceInstall>元素具有Account="NT AUTHORITY\LocalService",看起来像这样:

    <Component Id="Comp_File_OurServiceExe" Guid="*">
    
        <File Source="$(var.TargetDir)OurService.exe" id="File_OurServiceExe" KeyPath="yes" />
    
        <ServiceInstall
            Id           = "ServiceInstall_OurServiceExe"
            Vital        = "yes"
    
            Name         = "RussianSpyingService"
            DisplayName  = "Russian Spying Service"
            Description  = "Crawls your network for incriminating files to send to the FSB"
            Account      = "NT AUTHORITY\LocalService"
            Type         = "ownProcess"
            Arguments    = "-mode service"
            Interactive  = "no"
            Start        = "auto"
            ErrorControl = "normal"
        >
    
            <ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnUninstall="no"  OnReinstall="yes" />
            <util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="none" ResetPeriodInDays="1" />
        </ServiceInstall>
    </Component>
    
  • 遵循这些重复步骤后,服务注册/配置将被无意重置:

    1. 使用MSI 1.0.0版完成安装
    2. 打开Services.msc并将RussianSpyingService更改为使用NT AUTHORITY\NetworkService(而不是NT AUTHORITY\LocalService
    3. 使用相同的*.wxs文件创建一个新的MSI,但使用更高的文件版本,并为其提供更高的版本,例如1.0.1(不要忘记MSI仅使用版本号的前3个组件,而忽略第4个版本)
    4. 该安装完成后,观察RussianSpyingService已被重置为使用NT AUTHORITY\LocalService

顺便说一句,我问过FireGiant(他们的顾问以前曾在Microsoft工作过,曾帮助公司的其他团队使用MSI),其他SQL Server之类的软件能够使用MSI安装Windows Services,尽管之间的配置发生了变化,但它们仍然可以正常运行升级安装。他们告诉我,诸如SQL Server之类的产品经常将自定义动作用于Windows服务配置,尽管有避免自定义动作的一般建议,但它是可以接受的,因为Microsoft的SQL Server团队足够投入工程和测试资源来确保它们正常工作。 >

解决方案

  • 简而言之:“使用MSI属性!”
  • 具体来说,定义一个代表Account属性值的MSI属性,并在MSI启动期间从注册表中加载该值,如果该值不存在,则使用默认值NT AUTHORITY\LocalService
  • 理想情况下,属性值将存储在应用程序自己的注册表项中,应用程序负责确保该值与当前服务配置匹配。
    • 这可以通过在HKLM中创建一个新的注册表项来完成,该注册表项可以让LocalServiceNetworkService(或任何服务帐户)对其进行写入,因此当服务启动时,它在那里记录了其用户帐户的名称-但这很复杂。
    • 请勿使用HKCU来存储值,因为那样行不通:HKCU为不同用户解析为完全不同的注册表配置单元(甚至可能无法加载或访问)。
  • 从技术上讲,Microsoft不支持另一个选项,因为它使用Windows注册表自身的services注册密钥原始ObjectName(帐户名)值-可能采用与Windows相同的格式AccountName=""属性。这也是最实用的,如下所述:

这对我们有用:

  1. 在您的<Wix> ... <Product>...元素内,添加以下<Property>声明和<RegistrySearch />元素:

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix
        xmlns       = "http://schemas.microsoft.com/wix/2006/wi"
        xmlns:netfx = "http://schemas.microsoft.com/wix/NetFxExtension"
        xmlns:util  = "http://schemas.microsoft.com/wix/UtilExtension"
    >
    
        <Product
            Id="*"
            UpgradeCode="{your_const_GUID}"
            otherAttributes="goHere"
        >
    
            <!-- [...] -->
    
            <Property Id="SERVICE_ACCOUNT_NAME" Value="NT AUTHORITY\LocalService">
                <!-- Properties used in <RegistrySearch /> must be public (ALL_UPPERCASE), not private (AT_LEAST_1_lowercase_CHARACTER) -->
                <RegistrySearch Id="DetermineExistingServiceAccountName" Type="raw" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\RussianSpyingService" Name="ObjectName" />
            </Property>
    
            <!-- [...] -->
    
        </Product>
    </Wix>
    
  2. 更新您的<ServiceInstall元素,为SERVICE_ACCOUNT_NAME使用新的Account="" MSI属性,而不是之前的硬编码NT AUTHORITY\LocalService

    <ServiceInstall
        Id           = "ServiceInstall_OurServiceExe"
        Vital        = "yes"
    
        Name         = "RussianSpyingService"
        DisplayName  = "Russian Spying Service"
        Description  = "Crawls your network for incriminating files to send to the FSB"
        Account      = "[SERVICE_ACCOUNT_NAME]"
        Type         = "ownProcess"
        Arguments    = "-mode service"
        Interactive  = "no"
        Start        = "auto"
        ErrorControl = "normal"
    >
    
        <ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnUninstall="no"  OnReinstall="yes" />
        <util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="none" ResetPeriodInDays="1" />
    
    </ServiceInstall>
    
  3. 构建并运行安装程序并执行升级方案,您会看到在升级安装之间将保留所有自定义的服务帐户用户名。

您也可以将这种方法推广到其他属性。

免责声明:

  • Microsoft并未正式认可直接使用HKLM\SYSTEM\CurrentControlSet\Services\注册表项的用户土地程序。 Windows Services上的所有操作都应通过记录和受支持的Win32 Service Control Manager API:https://docs.microsoft.com/en-us/windows/desktop/services/service-control-manager
    • 这意味着Microsoft可以自行决定更改Windows Service配置,以便不再使用HKLM\SYSTEM\CurrentControlSet\Services\键。
    • (这可能会破坏很多第三方软件,如果微软这样做,他们可能会像使用SysWow6432Node一样向其中添加某种虚拟化或重新映射系统)。
  • 我仅使用LocalServiceNetworkService进行了测试。如果您在运行升级之前将服务配置修改为在安装后使用自定义用户帐户,我看不到会发生什么。我确实希望在这种情况下它还将保留配置,因为它将对SCM中的ObjectName值执行字符串比较,并且无法访问密码。

答案 1 :(得分:0)

最终为我工作的是

  <DeleteServices><![CDATA[REMOVE ~= "ALL" AND (NOT UPGRADINGPRODUCTCODE)]]> </DeleteServices>
  <InstallServices><![CDATA[NOT Installed]]> </InstallServices>

我通过一系列的尝试和错误尝试以及其他一些具有类似答案的线程的组合得出了这个答案。

仅无法正常运行的可能原因之一是因为WIX在重新安装时也会删除该服务。.在初始安装过程中,我们只希望安装一次该服务。我们还希望确保在卸载时删除该服务。这是对我有效的唯一条件组合,允许服务保留其设置和用户帐户。