我正在使用WiX处理MSI安装程序。我试图尽可能简化开发:这是一个内部产品,我的用户就是我们的IT人员。
该产品包含一项Windows服务,必须配置为在每台计算机的不同帐户下运行。
我为用户规划的工作流程(首次安装)如下:
sc
或本地服务小程序停止服务后续更新将包括从更新的MSI文件安装。
测试"小"更新,我很惊讶地发现安装程序将服务重置为在默认帐户下运行。这对我来说是一个主要问题,因为它使我的用户很难更新他们的服务器。每次有更新时,他们都必须在每台机器上重新输入帐户信息。我预计这会发生在" major"更新,但不是在"小"之一。
是否有办法配置安装程序,以便在" small"期间不会更改服务的现有帐户/密码配置。或者是"未成年人"更新吗
这会在"修复过程中发生吗? (我还没试过)?
这是我的组件在.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;升级。那不是我的经历。我的经历是侥幸吗?
在安装过程中提示输入帐户和密码会很好,但是在这种情况下将密码存储在注册表或其他地方并不是一个真正的选择,并且必须在每次更新时重新输入凭据就像破坏性一样必须手动重新配置服务。
答案 0 :(得分:0)
我今天与FireGiant进行了有关此确切问题的咨询电话,我们找到了解决方案。
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>
遵循这些重复步骤后,服务注册/配置将被无意重置:
Services.msc
并将RussianSpyingService
更改为使用NT AUTHORITY\NetworkService
(而不是NT AUTHORITY\LocalService
)*.wxs
文件创建一个新的MSI,但使用更高的文件版本,并为其提供更高的版本,例如1.0.1(不要忘记MSI仅使用版本号的前3个组件,而忽略第4个版本)RussianSpyingService
已被重置为使用NT AUTHORITY\LocalService
。顺便说一句,我问过FireGiant(他们的顾问以前曾在Microsoft工作过,曾帮助公司的其他团队使用MSI),其他SQL Server之类的软件能够使用MSI安装Windows Services,尽管之间的配置发生了变化,但它们仍然可以正常运行升级安装。他们告诉我,诸如SQL Server之类的产品经常将自定义动作用于Windows服务配置,尽管有避免自定义动作的一般建议,但它是可以接受的,因为Microsoft的SQL Server团队足够投入工程和测试资源来确保它们正常工作。 >
Account
属性值的MSI属性,并在MSI启动期间从注册表中加载该值,如果该值不存在,则使用默认值NT AUTHORITY\LocalService
。HKLM
中创建一个新的注册表项来完成,该注册表项可以让LocalService
或NetworkService
(或任何服务帐户)对其进行写入,因此当服务启动时,它在那里记录了其用户帐户的名称-但这很复杂。HKCU
来存储值,因为那样行不通:HKCU
为不同用户解析为完全不同的注册表配置单元(甚至可能无法加载或访问)。services
注册密钥原始ObjectName
(帐户名)值-可能采用与Windows相同的格式AccountName=""
属性。这也是最实用的,如下所述:这对我们有用:
在您的<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>
更新您的<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>
构建并运行安装程序并执行升级方案,您会看到在升级安装之间将保留所有自定义的服务帐户用户名。
您也可以将这种方法推广到其他属性。
免责声明:
HKLM\SYSTEM\CurrentControlSet\Services\
注册表项的用户土地程序。 Windows Services上的所有操作都应通过记录和受支持的Win32 Service Control Manager API:https://docs.microsoft.com/en-us/windows/desktop/services/service-control-manager
HKLM\SYSTEM\CurrentControlSet\Services\
键。 SysWow6432Node
一样向其中添加某种虚拟化或重新映射系统)。LocalService
和NetworkService
进行了测试。如果您在运行升级之前将服务配置修改为在安装后使用自定义用户帐户,我看不到会发生什么。我确实希望在这种情况下它还将保留配置,因为它将对SCM中的ObjectName
值执行字符串比较,并且无法访问密码。答案 1 :(得分:0)
最终为我工作的是
<DeleteServices><![CDATA[REMOVE ~= "ALL" AND (NOT UPGRADINGPRODUCTCODE)]]> </DeleteServices>
<InstallServices><![CDATA[NOT Installed]]> </InstallServices>
我通过一系列的尝试和错误尝试以及其他一些具有类似答案的线程的组合得出了这个答案。
仅无法正常运行的可能原因之一是因为WIX在重新安装时也会删除该服务。.在初始安装过程中,我们只希望安装一次该服务。我们还希望确保在卸载时删除该服务。这是对我有效的唯一条件组合,允许服务保留其设置和用户帐户。