MSI安装程序中更新的服务名称并重新安装/升级时出错
我有一个MSI来安装一些服务。我更改了其中一个名称并在Wix文件中更新了引用。MSI安装程序中更新的服务名称并重新安装/升级时出错
它工作正常,当我刚刚安装它作为新鲜的微星。然而,当有升级方案(其中安装有旧的服务名称MSI和我尝试安装这个新的MSI具有服务名称改变的一个),我收到以下错误:
这里有什么提示吗?我只是在.wxs文件中重命名。我是否必须使用现有的组件ID卸载旧的组件,并用新的组件ID命名新组件ID?
当前,使用带有新名称的旧组件ID。
旧程序的部分代码:
<Directory Id="dirxxx" Name="oldname">
<!-- oldname service-->
<Component Id="cmpOldNameService" Guid="bbb"
SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
Win64="no" Location="either">
<RemoveFile Id="ccc" On="uninstall" Name="z.dll"/>
<File Id="ccc" KeyPath="no" Source="$(var.xSource)\OldNameService\a.dll"/>
<File Id="ddd" KeyPath="no" Source="$(var.xSource)\OldNameService\b.dll"/>
<File Id="eee" KeyPath="no" Source="$(var.xSource)\OldNameService\c.dll"/>
<File Id="fff" KeyPath="no" Source="$(var.xSource)\OldNameService\d.dll"/>
<File Id="ggg" KeyPath="no" Source="$(var.xSource)\OldNameService\e.dll"/>
<File Id="hhh" KeyPath="no" Source="$(var.xSource)\OldNameService\f.dll"/>
<File Id="iii" KeyPath="yes" Source="$(var.xSource)\OldNameService\g.exe"/>
<File Id="jjj" KeyPath="no" Source="$(var.xSource)\OldNameService\h.dll"/>
<File Id="kkk" KeyPath="no" Source="$(var.xSource)\OldNameService\i.dll"/>
<ServiceInstall Id="OldNameService" DisplayName="OldName Service" Name="NewName"
ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" Description="OldName Service">
<ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes"/>
</ServiceInstall>
<ServiceControl Id="OldNameServiceControl" Name="NewName"
Start="install" Stop="uninstall" Remove="uninstall" Wait="no"/>
</Component>
<Component Id="lll" Guid="mmm" NeverOverwrite="yes">
<File Id="nnn" KeyPath="yes" Source="$(var.xSource)\OldNameService\OldName.exe.config"/>
<util:XmlFile Id="UpdateOldNamelogFileName"
File="[#nnn]"
Action="setValue"
ElementPath="/configuration/appSettings/add[\[]@key='logFile'[\]]/@value"
Value="[ooo]oldname_YYYYMM.log" />
</Component>
从新的代码代替:
<Directory Id="dirxxx" Name="newname">
<!-- newname service-->
<Component Id="cmpNewNameService" Guid="bbb"
SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
Win64="no" Location="either">
<RemoveFile Id="ccc" On="uninstall" Name="z.dll"/>
<File Id="ccc" KeyPath="no" Source="$(var.xSource)\NewNameService\a.dll"/>
<File Id="ddd" KeyPath="no" Source="$(var.xSource)\NewNameService\b.dll"/>
<File Id="eee" KeyPath="no" Source="$(var.xSource)\NewNameService\c.dll"/>
<File Id="fff" KeyPath="no" Source="$(var.xSource)\NewNameService\d.dll"/>
<File Id="ggg" KeyPath="no" Source="$(var.xSource)\NewNameService\e.dll"/>
<File Id="hhh" KeyPath="no" Source="$(var.xSource)\NewNameService\f.dll"/>
<File Id="iii" KeyPath="yes" Source="$(var.xSource)\NewNameService\g.exe"/>
<File Id="jjj" KeyPath="no" Source="$(var.xSource)\NewNameService\h.dll"/>
<File Id="kkk" KeyPath="no" Source="$(var.xSource)\NewNameService\i.dll"/>
<ServiceInstall Id="NewNameService" DisplayName="NewName Service" Name="NewName"
ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" Description="New Name Service">
<ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes"/>
</ServiceInstall>
<ServiceControl Id="NewNameServiceControl" Name="NewName"
Start="install" Stop="uninstall" Remove="uninstall" Wait="no"/>
</Component>
<Component Id="lll" Guid="mmm" NeverOverwrite="yes">
<File Id="nnn" KeyPath="yes" Source="$(var.xSource)\NewNameService\NewName.exe.config"/>
<util:XmlFile Id="UpdateNewNamelogFileName"
File="[#nnn]"
Action="setValue"
ElementPath="/configuration/appSettings/add[\[]@key='logFile'[\]]/@value"
Value="[ooo]newservice_YYYYMM.log" />
</Component>
所以,我能在这里解决我的问题。我想做一个小小的升级,并在ServiceInstall
中添加Account
属性Network Service
。
<ServiceInstall Id="Service1" DisplayName="My Service" Name="MyService"
ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" Description="My Service" Account="NT Authority\NetworkService">
这成为太久添加为一个评论,我加入这个作为一个答案,虽然它也许没有按不为你回答:
- 最明显的“错误”或至少是非标准的问题是,你有很多的二进制文件在一个单一的组件。这是不是最佳实践(事实上很糟糕的做法)。
- 在您做任何事情之前,请拆分您的组件,并且为每个文件创建一个组件。我总是对每个组件使用单个文件,即使对于非二进制文件也是如此,但最佳做法指出,您应始终为二进制文件使用单独的组件。实质上,这是正确部署的要求。
- 为了保持它非常简短:如果将多个文件保存在同一个组件中,则只有其中一个文件是关键文件。如果该文件没有增加其版本号(对于二进制文件),则所有其他文件也不会更新 - 即使它们的版本增加了。只有密钥文件确定组件是否安装。而一个组件只能作为一个整体安装,或者根本不安装。
- 事情对于非版本化文件以类似的方式工作,但它不是被检查的版本,而是文件是否被修改。如果磁盘上的文件已被修改,则该组件是而不是安装了。请阅读MSDN文章File Versioning Rules。您也可以在同一问题上检查this Symantec article。而这个问题的答案是值得一读(与克里斯画家的评论一起):File Versioning Rules When Neither Components Has a Key File
- 如果您的应用程序的“真人版”我会使用一个重大升级与RemoveExistingProducts年初预定InstallExecuteSequence。用简单的英语表示您将在安装新版本之前完全卸载以前的版本。这应该消除您的组件创建错误或其他任何错误之后的任何错误。我没有看得太彻底,但这个答案(第一个)似乎是如何安排主要升级的好的解释:How to get WiX major upgrade working?。或者直接找到源文件并输入check the WiX 3 documentation for how to implement a major upgrade,只是为了保证测量的准确性,我包含此链接:How to implement WiX installer upgrade?
- 除此之外,我想建议您“简化”您的WiX XML,如本答复中所述:Syntax for guids in WIX?。您定义的属性越少,读取文件内容越容易,并且可以隐藏的错误越少(稍后可以更容易地以XML格式升级)。
- 请试试这个“部分修复”和重大升级调整先来看看是否能解决你的问题。并尝试使用source simplification。
我想通这个问题,但还没有找到解决办法。所以我必须卸载旧服务及其所有组件,然后安装新服务。 – Atihska
什么应该是我的ServiceControl和ServiceInstall元素?他们都需要用于已安装的旧服务吗?另外,我是否需要将RemoveFolder添加到该目录中的每个组件? – Atihska
我会安排一次重要的升级,在安装新版本之前彻底卸载旧版本。这涉及在InstallExecuteSequence中的InstallInitialize之前运行RemoveExistingProducts。我会将ServiceControl和ServiceInstall元素放在保存主要服务可执行文件的组件中。我假设您已将您的设置转换为每个文件使用一个组件? –
您可以重命名在更新设置服务文件?如果可以,请尝试重命名服务文件并为其指定一个新的组件GUID。 –
重大升级还是小升级? –
@SteinÅsmul编辑我的帖子并添加了代码。 – Atihska