升级期间未(仅)复制文件
File not copied (only) during upgrade
概述
对于我的产品的新版本 v1.9.0,我创建了一个新的 MSI 安装程序。该应用程序的上一个版本是v1.7.0.
卸载旧版本然后安装新版本就可以了。
但是当我尝试使用 v1.9.0 安装程序更新旧版本时,正好缺少一个文件 (NLog.dll)。所有其他文件都被复制得很好。
我正在使用 heat.exe 为我的应用程序的所有依赖项创建组件。所以 NLog.dll 的处理方式与所有其他文件完全相同,但它是唯一显示这种奇怪行为的文件。
NLog.dll 从升级到 v1.9.0
的日志片段
这些是该文件的相关日志片段。
第 5174 行:
MSI (s) (E4:1C) [17:12:42:343]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 37733 行:
MSI (s) (E4:1C) [17:13:12:252]: Executing op: FileRemove(,FileName=NLog.dll,,ComponentId={53AAD98D-AFDB-4D70-ADCC-5305C3174ED5})
RemoveFiles: File: NLog.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\
MSI (s) (E4:1C) [17:13:12:260]: Verifying accessibility of file: NLog.dll
MSI (s) (E4:1C) [17:13:12:264]: Note: 1: 2318 2:
MSI (s) (E4:1C) [17:13:12:267]: Note: 1: 2318 2:
第 50386 行:
MSI (s) (E4:DC) [17:13:22:442]: Executing op: ComponentRegister(ComponentId={D4B31A07-4F5F-4DAA-8280-9A782110477A},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll,State=3,,Disk=1,SharedDllRefCount=2,BinaryType=0)
1: {C2F509F4-A1F9-4377-89FE-59B4DB664FB7} 2: {D4B31A07-4F5F-4DAA-8280-9A782110477A} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll
MSI (s) (E4:DC) [17:13:22:442]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
从升级到 v1.9.0 的一些其他文件的日志片段
为了比较,这里是一些随机的其他文件 (NLog.Extensions.Logging.dll) 的日志片段,它按预期更新。
第 5173 行:
MSI (s) (E4:1C) [17:12:42:342]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 37738 行:
MSI (s) (E4:1C) [17:13:12:267]: Executing op: FileRemove(,FileName=NLog.Extensions.Logging.dll,,ComponentId={2CE3E451-CBCA-4D6A-953A-0EEC1F23FE33})
RemoveFiles: File: NLog.Extensions.Logging.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\
MSI (s) (E4:1C) [17:13:12:269]: Verifying accessibility of file: NLog.Extensions.Logging.dll
MSI (s) (E4:1C) [17:13:12:272]: Note: 1: 2318 2:
MSI (s) (E4:1C) [17:13:12:276]: Note: 1: 2318 2:
第 50389 行:
MSI (s) (E4:DC) [17:13:22:442]: Executing op: ComponentRegister(ComponentId={0DFB8E8D-FD31-430F-A84B-C21D7BCB296B},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll,State=3,,Disk=1,SharedDllRefCount=2,BinaryType=0)
1: {C2F509F4-A1F9-4377-89FE-59B4DB664FB7} 2: {0DFB8E8D-FD31-430F-A84B-C21D7BCB296B} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll
MSI (s) (E4:DC) [17:13:22:442]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 51640 行:
MSI (s) (E4:DC) [17:13:23:148]: Executing op: FileCopy(SourceName=c7dqtb1j.dll|NLog.Extensions.Logging.dll,SourceCabKey=filC5C20BE40C004EEC9809A0196347239A,DestName=NLog.Extensions.Logging.dll,Attributes=512,FileSize=24064,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=1.3.0.804,Language=0,InstallMode=58982400,,,,,,,)
MSI (s) (E4:DC) [17:13:23:149]: File: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll; To be installed; Won't patch; No existing file
MSI (s) (E4:DC) [17:13:23:149]: Source for file 'filC5C20BE40C004EEC9809A0196347239A' is compressed
InstallFiles: File: NLog.Extensions.Logging.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\, Size: 24064
日志片段分析
如您所见,NLog.dll 和其他文件的前三个片段看起来几乎相同。但是在 NLog.dll.
的情况下,文件实际被复制的最后一部分只是丢失了
日志中没有任何内容可以(向我)解释为什么 NLog.dll 没有被复制。
原始 v1.7.0 安装的日志片段
我不知道这是否相关,但这是原始安装中这两个文件的相关日志片段。也许这些很重要,因为它们在原始安装期间具有 ID。
第 5316 行(NLog.dll):
MSI (s) (E4:94) [17:11:14:734]: Executing op: ComponentRegister(ComponentId={53AAD98D-AFDB-4D70-ADCC-5305C3174ED5},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)
1: {D6410853-B366-4D05-A1A3-93FC3EFF982A} 2: {53AAD98D-AFDB-4D70-ADCC-5305C3174ED5} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll
MSI (s) (E4:94) [17:11:14:734]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 5319 行(NLog.Extensions.Logging.dll):
MSI (s) (E4:94) [17:11:14:734]: Executing op: ComponentRegister(ComponentId={2CE3E451-CBCA-4D6A-953A-0EEC1F23FE33},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)
1: {D6410853-B366-4D05-A1A3-93FC3EFF982A} 2: {2CE3E451-CBCA-4D6A-953A-0EEC1F23FE33} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll
MSI (s) (E4:94) [17:11:14:735]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 19183 行(NLog.dll):
MSI (s) (E4:94) [17:11:17:881]: Executing op: FileCopy(SourceName=NLog.dll,SourceCabKey=fil3052FED1115C64C0B25CEB4ED20F217C,DestName=NLog.dll,Attributes=512,FileSize=422400,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=5.0.0.0,Language=0,InstallMode=58982400,,,,,,,)
MSI (s) (E4:94) [17:11:17:882]: File: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll; To be installed; Won't patch; No existing file
MSI (s) (E4:94) [17:11:17:882]: Source for file 'fil3052FED1115C64C0B25CEB4ED20F217C' is compressed
InstallFiles: File: NLog.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\, Size: 422400
第 31615 行(NLog.Extensions.Logging.dll):
MSI (s) (E4:94) [17:11:22:509]: Executing op: FileCopy(SourceName=c7dqtb1j.dll|NLog.Extensions.Logging.dll,SourceCabKey=filC5C20BE40C004EEC9809A0196347239A,DestName=NLog.Extensions.Logging.dll,Attributes=512,FileSize=8704,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=1.0.0.0,Language=0,InstallMode=58982400,,,,,,,)
MSI (s) (E4:94) [17:11:22:509]: File: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll; To be installed; Won't patch; No existing file
MSI (s) (E4:94) [17:11:22:509]: Source for file 'filC5C20BE40C004EEC9809A0196347239A' is compressed
InstallFiles: File: NLog.Extensions.Logging.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\, Size: 8704
一些相关的配置片段
为了收集依赖关系,我 运行 heat.exe 像这样:
"%WIX%\bin\heat" dir "$(ProjectDir)\obj\PublishOutput" -dr BinFolder -ke -srd -sreg -cg MyComponentGroup -var var.TempPublishDir -gg -out "$(ProjectDir)\obj\MyContent.wxs"
生成的组件如下所示:
<Component Id="cmpE15B2B75697ADA78CA21A063FF464A7F" Directory="BinFolder" Guid="{876C7C40-4FD9-464E-9282-5CE83B56C4C9}">
<File Id="fil3052FED1115C64C0B25CEB4ED20F217C" KeyPath="yes" Source="$(var.TempPublishDir)\NLog.dll" />
</Component>
<Component Id="cmpF5B8522DF5AB91BD2DBBA73CBCD944B8" Directory="BinFolder" Guid="{EFB396C4-4F10-4C1B-92FB-75D5C616A708}">
<File Id="filC5C20BE40C004EEC9809A0196347239A" KeyPath="yes" Source="$(var.TempPublishDir)\NLog.Extensions.Logging.dll" />
</Component>
以及产品定义的相关部分:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" Name="xxx" Language="1033" Version="1.9.0.0" Manufacturer="xxx" UpgradeCode="ab9f8a5a-aa60-4327-9299-3f928136a6e4">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
</Product>
</Wix>
我考虑过的事情
有个非常相似的问题here. The important thing seems to to be to execute RemoveExistingProducts
as early as possible. If I understand this正确,使用MajorUpgrade
指令(我用的),默认很早就执行RemoveExistingProducts
。所以我想我在这里应该是安全的。
我还尝试使用 -ag
参数而不是 -gg
运行ning heat.exe。这会将所有组件的 Guid 更改为 "*"
。但这并没有什么区别。
我在升级日志的第 9003 行注意到的一件事是:MSI (s) (E4:1C) [17:12:46:123]: Skipping RemoveExistingProducts action: current configuration is maintenance mode or an uninstall
。也许这表明存在一些潜在问题。但是当我在升级过程中查看我的应用程序的实际 bin 文件夹时,我可以清楚地看到首先所有文件都被删除,然后我可以看到该文件夹是如何再次填充的(但不是 NLog.dll).
所有这些并不能真正解释为什么升级对所有其他文件都能正常工作,但对一个文件却不行。我也用类似的安装程序部署了我产品的几个以前版本,我以前从未遇到过这个问题。
您正在尝试降级 NLog.dll 的版本。 MSI 中存在导致文件被删除而不是重新安装的错误。唯一的解决方法是完全卸载然后重新安装。
解决这个问题的关键提示来自 Bob Arnson:
You're trying to downgrade the version of NLog.dll. There's a bug in MSI that causes the file to be removed and not reinstalled.
事实上,我的软件的最新版本引用的 NLog.dll 版本比我的软件的以前版本要旧。
NLog.dll其实是我软件的间接依赖。我引用的是 NLog.Web.AspNetCore.dll,它又引用了 NLog.Extensions.Logging.dll 和 NLog.dll,所以我都没有意识到有NLog.dll.
的版本降级
强迫客户 uninstall/reinstall 不是一种选择。但是我找到了解决方案 here.
我创建了以下 XSL 转换,它从热输出中删除了三个单独的 NLog 组件,而是插入了一个包含所有三个文件的新组件,并且在我直接引用的文件上设置了 KeyPath:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns="http://schemas.microsoft.com/wix/2006/wi" exclude-result-prefixes="xsl wix">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Remove individual components for NLog files and add the files in a single component, see CT-1886 -->
<!-- -->
<xsl:key name="NLogFilesToRemove" match="wix:Component[contains(wix:File/@Source, 'NLog.dll') or contains(wix:File/@Source, 'NLog.Extensions.Logging.dll') or contains(wix:File/@Source, 'NLog.Web.AspNetCore.dll')]" use="@Id" />
<xsl:template match="*[self::wix:Component or self::wix:ComponentRef][key('NLogFilesToRemove', @Id)]" />
<xsl:template match="wix:ComponentGroup">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<Component Id="cmpBundledNLog" Directory="BinFolder" Guid="0d590e51-18bd-455a-9edf-c4ff34cce42e">
<File Id="fileNLogDll" KeyPath="no" Source="$(var.TempPublishDir)\NLog.dll" />
<File Id="fileNLogExtensionsLoggingDll" KeyPath="no" Source="$(var.TempPublishDir)\NLog.Extensions.Logging.dll" />
<File Id="fileNLogWebAspNetCoreDll" KeyPath="yes" Source="$(var.TempPublishDir)\NLog.Web.AspNetCore.dll" />
</Component>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我不确定这会在未来造成的并发症(在某些时候我想摆脱这种解决方法),但现在它似乎工作正常。
您正在尝试降级 NLog.Extensions.Logging.dll
MSI 的默认配置不允许这样做,但是您可以通过显式指定安装程序的 REINSTALLMODE 来覆盖它。
这可以通过覆盖主 wix 文件的产品部分中的相应 属性 以允许降级来实现
<Product Id="*"
Name="MY SOFTWARE $(var.Version) $(var.Platform)"
Language="1033"
Version="$(var.Version)"
Manufacturer="The Umbrela Corporation"
UpgradeCode="someguid-guid-guid-guid-someguid">
...
<Property Id="REINSTALLMODE" Value="dmus"/>
...
概述
对于我的产品的新版本 v1.9.0,我创建了一个新的 MSI 安装程序。该应用程序的上一个版本是v1.7.0.
卸载旧版本然后安装新版本就可以了。
但是当我尝试使用 v1.9.0 安装程序更新旧版本时,正好缺少一个文件 (NLog.dll)。所有其他文件都被复制得很好。
我正在使用 heat.exe 为我的应用程序的所有依赖项创建组件。所以 NLog.dll 的处理方式与所有其他文件完全相同,但它是唯一显示这种奇怪行为的文件。
NLog.dll 从升级到 v1.9.0
的日志片段这些是该文件的相关日志片段。
第 5174 行:
MSI (s) (E4:1C) [17:12:42:343]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 37733 行:
MSI (s) (E4:1C) [17:13:12:252]: Executing op: FileRemove(,FileName=NLog.dll,,ComponentId={53AAD98D-AFDB-4D70-ADCC-5305C3174ED5})
RemoveFiles: File: NLog.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\
MSI (s) (E4:1C) [17:13:12:260]: Verifying accessibility of file: NLog.dll
MSI (s) (E4:1C) [17:13:12:264]: Note: 1: 2318 2:
MSI (s) (E4:1C) [17:13:12:267]: Note: 1: 2318 2:
第 50386 行:
MSI (s) (E4:DC) [17:13:22:442]: Executing op: ComponentRegister(ComponentId={D4B31A07-4F5F-4DAA-8280-9A782110477A},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll,State=3,,Disk=1,SharedDllRefCount=2,BinaryType=0)
1: {C2F509F4-A1F9-4377-89FE-59B4DB664FB7} 2: {D4B31A07-4F5F-4DAA-8280-9A782110477A} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll
MSI (s) (E4:DC) [17:13:22:442]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
从升级到 v1.9.0 的一些其他文件的日志片段
为了比较,这里是一些随机的其他文件 (NLog.Extensions.Logging.dll) 的日志片段,它按预期更新。
第 5173 行:
MSI (s) (E4:1C) [17:12:42:342]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 37738 行:
MSI (s) (E4:1C) [17:13:12:267]: Executing op: FileRemove(,FileName=NLog.Extensions.Logging.dll,,ComponentId={2CE3E451-CBCA-4D6A-953A-0EEC1F23FE33})
RemoveFiles: File: NLog.Extensions.Logging.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\
MSI (s) (E4:1C) [17:13:12:269]: Verifying accessibility of file: NLog.Extensions.Logging.dll
MSI (s) (E4:1C) [17:13:12:272]: Note: 1: 2318 2:
MSI (s) (E4:1C) [17:13:12:276]: Note: 1: 2318 2:
第 50389 行:
MSI (s) (E4:DC) [17:13:22:442]: Executing op: ComponentRegister(ComponentId={0DFB8E8D-FD31-430F-A84B-C21D7BCB296B},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll,State=3,,Disk=1,SharedDllRefCount=2,BinaryType=0)
1: {C2F509F4-A1F9-4377-89FE-59B4DB664FB7} 2: {0DFB8E8D-FD31-430F-A84B-C21D7BCB296B} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll
MSI (s) (E4:DC) [17:13:22:442]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 51640 行:
MSI (s) (E4:DC) [17:13:23:148]: Executing op: FileCopy(SourceName=c7dqtb1j.dll|NLog.Extensions.Logging.dll,SourceCabKey=filC5C20BE40C004EEC9809A0196347239A,DestName=NLog.Extensions.Logging.dll,Attributes=512,FileSize=24064,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=1.3.0.804,Language=0,InstallMode=58982400,,,,,,,)
MSI (s) (E4:DC) [17:13:23:149]: File: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll; To be installed; Won't patch; No existing file
MSI (s) (E4:DC) [17:13:23:149]: Source for file 'filC5C20BE40C004EEC9809A0196347239A' is compressed
InstallFiles: File: NLog.Extensions.Logging.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\, Size: 24064
日志片段分析
如您所见,NLog.dll 和其他文件的前三个片段看起来几乎相同。但是在 NLog.dll.
的情况下,文件实际被复制的最后一部分只是丢失了日志中没有任何内容可以(向我)解释为什么 NLog.dll 没有被复制。
原始 v1.7.0 安装的日志片段
我不知道这是否相关,但这是原始安装中这两个文件的相关日志片段。也许这些很重要,因为它们在原始安装期间具有 ID。
第 5316 行(NLog.dll):
MSI (s) (E4:94) [17:11:14:734]: Executing op: ComponentRegister(ComponentId={53AAD98D-AFDB-4D70-ADCC-5305C3174ED5},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)
1: {D6410853-B366-4D05-A1A3-93FC3EFF982A} 2: {53AAD98D-AFDB-4D70-ADCC-5305C3174ED5} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll
MSI (s) (E4:94) [17:11:14:734]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 5319 行(NLog.Extensions.Logging.dll):
MSI (s) (E4:94) [17:11:14:734]: Executing op: ComponentRegister(ComponentId={2CE3E451-CBCA-4D6A-953A-0EEC1F23FE33},KeyPath=C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)
1: {D6410853-B366-4D05-A1A3-93FC3EFF982A} 2: {2CE3E451-CBCA-4D6A-953A-0EEC1F23FE33} 3: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll
MSI (s) (E4:94) [17:11:14:735]: WIN64DUALFOLDERS: Substitution in 'C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll' folder had been blocked by the 1 mask argument (the folder pair's iSwapAttrib member = 0).
第 19183 行(NLog.dll):
MSI (s) (E4:94) [17:11:17:881]: Executing op: FileCopy(SourceName=NLog.dll,SourceCabKey=fil3052FED1115C64C0B25CEB4ED20F217C,DestName=NLog.dll,Attributes=512,FileSize=422400,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=5.0.0.0,Language=0,InstallMode=58982400,,,,,,,)
MSI (s) (E4:94) [17:11:17:882]: File: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.dll; To be installed; Won't patch; No existing file
MSI (s) (E4:94) [17:11:17:882]: Source for file 'fil3052FED1115C64C0B25CEB4ED20F217C' is compressed
InstallFiles: File: NLog.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\, Size: 422400
第 31615 行(NLog.Extensions.Logging.dll):
MSI (s) (E4:94) [17:11:22:509]: Executing op: FileCopy(SourceName=c7dqtb1j.dll|NLog.Extensions.Logging.dll,SourceCabKey=filC5C20BE40C004EEC9809A0196347239A,DestName=NLog.Extensions.Logging.dll,Attributes=512,FileSize=8704,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=1.0.0.0,Language=0,InstallMode=58982400,,,,,,,)
MSI (s) (E4:94) [17:11:22:509]: File: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\NLog.Extensions.Logging.dll; To be installed; Won't patch; No existing file
MSI (s) (E4:94) [17:11:22:509]: Source for file 'filC5C20BE40C004EEC9809A0196347239A' is compressed
InstallFiles: File: NLog.Extensions.Logging.dll, Directory: C:\Program Files (x86)\Cisco\DiagnosticBridge\bin\, Size: 8704
一些相关的配置片段
为了收集依赖关系,我 运行 heat.exe 像这样:
"%WIX%\bin\heat" dir "$(ProjectDir)\obj\PublishOutput" -dr BinFolder -ke -srd -sreg -cg MyComponentGroup -var var.TempPublishDir -gg -out "$(ProjectDir)\obj\MyContent.wxs"
生成的组件如下所示:
<Component Id="cmpE15B2B75697ADA78CA21A063FF464A7F" Directory="BinFolder" Guid="{876C7C40-4FD9-464E-9282-5CE83B56C4C9}">
<File Id="fil3052FED1115C64C0B25CEB4ED20F217C" KeyPath="yes" Source="$(var.TempPublishDir)\NLog.dll" />
</Component>
<Component Id="cmpF5B8522DF5AB91BD2DBBA73CBCD944B8" Directory="BinFolder" Guid="{EFB396C4-4F10-4C1B-92FB-75D5C616A708}">
<File Id="filC5C20BE40C004EEC9809A0196347239A" KeyPath="yes" Source="$(var.TempPublishDir)\NLog.Extensions.Logging.dll" />
</Component>
以及产品定义的相关部分:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" Name="xxx" Language="1033" Version="1.9.0.0" Manufacturer="xxx" UpgradeCode="ab9f8a5a-aa60-4327-9299-3f928136a6e4">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
</Product>
</Wix>
我考虑过的事情
有个非常相似的问题here. The important thing seems to to be to execute
RemoveExistingProducts
as early as possible. If I understand this正确,使用MajorUpgrade
指令(我用的),默认很早就执行RemoveExistingProducts
。所以我想我在这里应该是安全的。我还尝试使用
-ag
参数而不是-gg
运行ning heat.exe。这会将所有组件的 Guid 更改为"*"
。但这并没有什么区别。我在升级日志的第 9003 行注意到的一件事是:
MSI (s) (E4:1C) [17:12:46:123]: Skipping RemoveExistingProducts action: current configuration is maintenance mode or an uninstall
。也许这表明存在一些潜在问题。但是当我在升级过程中查看我的应用程序的实际 bin 文件夹时,我可以清楚地看到首先所有文件都被删除,然后我可以看到该文件夹是如何再次填充的(但不是 NLog.dll).
所有这些并不能真正解释为什么升级对所有其他文件都能正常工作,但对一个文件却不行。我也用类似的安装程序部署了我产品的几个以前版本,我以前从未遇到过这个问题。
您正在尝试降级 NLog.dll 的版本。 MSI 中存在导致文件被删除而不是重新安装的错误。唯一的解决方法是完全卸载然后重新安装。
解决这个问题的关键提示来自 Bob Arnson:
You're trying to downgrade the version of NLog.dll. There's a bug in MSI that causes the file to be removed and not reinstalled.
事实上,我的软件的最新版本引用的 NLog.dll 版本比我的软件的以前版本要旧。
NLog.dll其实是我软件的间接依赖。我引用的是 NLog.Web.AspNetCore.dll,它又引用了 NLog.Extensions.Logging.dll 和 NLog.dll,所以我都没有意识到有NLog.dll.
的版本降级强迫客户 uninstall/reinstall 不是一种选择。但是我找到了解决方案 here.
我创建了以下 XSL 转换,它从热输出中删除了三个单独的 NLog 组件,而是插入了一个包含所有三个文件的新组件,并且在我直接引用的文件上设置了 KeyPath:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns="http://schemas.microsoft.com/wix/2006/wi" exclude-result-prefixes="xsl wix">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>
<!-- Identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Remove individual components for NLog files and add the files in a single component, see CT-1886 -->
<!-- -->
<xsl:key name="NLogFilesToRemove" match="wix:Component[contains(wix:File/@Source, 'NLog.dll') or contains(wix:File/@Source, 'NLog.Extensions.Logging.dll') or contains(wix:File/@Source, 'NLog.Web.AspNetCore.dll')]" use="@Id" />
<xsl:template match="*[self::wix:Component or self::wix:ComponentRef][key('NLogFilesToRemove', @Id)]" />
<xsl:template match="wix:ComponentGroup">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<Component Id="cmpBundledNLog" Directory="BinFolder" Guid="0d590e51-18bd-455a-9edf-c4ff34cce42e">
<File Id="fileNLogDll" KeyPath="no" Source="$(var.TempPublishDir)\NLog.dll" />
<File Id="fileNLogExtensionsLoggingDll" KeyPath="no" Source="$(var.TempPublishDir)\NLog.Extensions.Logging.dll" />
<File Id="fileNLogWebAspNetCoreDll" KeyPath="yes" Source="$(var.TempPublishDir)\NLog.Web.AspNetCore.dll" />
</Component>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我不确定这会在未来造成的并发症(在某些时候我想摆脱这种解决方法),但现在它似乎工作正常。
您正在尝试降级 NLog.Extensions.Logging.dll MSI 的默认配置不允许这样做,但是您可以通过显式指定安装程序的 REINSTALLMODE 来覆盖它。
这可以通过覆盖主 wix 文件的产品部分中的相应 属性 以允许降级来实现
<Product Id="*"
Name="MY SOFTWARE $(var.Version) $(var.Platform)"
Language="1033"
Version="$(var.Version)"
Manufacturer="The Umbrela Corporation"
UpgradeCode="someguid-guid-guid-guid-someguid">
...
<Property Id="REINSTALLMODE" Value="dmus"/>
...