升级期间未复制文件(仅)

时间:2018-10-25 15:58:43

标签: wix windows-installer msiexec

概述

对于产品的新版本v1.9.0,我创建了一个新的MSI安装程序。该应用程序的先前版本是v1.7.0。

卸载旧版本,然后安装新版本可以正常工作。

但是,当我尝试使用v1.9.0安装程序更新旧版本时,恰好缺少一个文件( NLog.dll )。所有其他文件都可以复制。

我正在使用heat.exe为应用程序的所有依赖关系创建组件。因此, NLog.dll 的处理方式与其他文件完全相同,但这是唯一显示出这种奇怪行为的文件。

从升级到v1.9.0的 NLog.dll 的

日志片段

这些是与此文件相关的日志片段。

第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。重要的事情似乎是尽早执行RemoveExistingProducts。如果我正确地理解了this,则使用MajorUpgrade指令(我使用),默认情况下会非常早地执行RemoveExistingProducts。所以我认为我应该在这里安全。

  • 我还尝试使用-ag参数而不是-gg运行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 < / em>)。

所有这些都不能真正解释为什么升级对所有其他文件都能正常进行,而对一个文件却不能正常进行的原因。另外,我已经使用类似的安装程序部署了该产品的多个先前版本,而我以前从未遇到过此问题。

3 个答案:

答案 0 :(得分:2)

您正试图降级NLog.dll的版本。 MSI中存在一个错误,该错误导致文件被删除而不是重新安装。唯一的解决方法是完全卸载然后重新安装。

答案 1 :(得分:1)

解决这个问题的关键提示来自鲍勃·阿恩森:

  

您正试图降级NLog.dll的版本。 MSI中存在一个错误,该错误导致文件被删除而不是重新安装。

事实上,我软件的最新版本引用的是比以前软件版本更旧的 NLog.dll 版本。

NLog.dll 实际上是我的软件的间接依赖关系。我引用的是 NLog.Web.AspNetCore.dll ,而该引用又引用了 NLog.Extensions.Logging.dll NLog.dll ,因此我甚至没有意识到版本 NLog.dll 的降级。

不能强迫客户卸载/重新安装。但是我找到了解决方法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 -->
  <!-- https://stackoverflow.com/questions/44765707/how-to-exclude-files-in-wix-toolset -->
  <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>

我不确定将来会带来什么复杂性(有时我想摆脱这种变通方法),但目前看来还可以。

答案 2 :(得分:-1)

您正在尝试降级NLog.Extensions.Logging.dll MSI的默认配置不允许这样做,但是您可以通过明确指定istaller的REINSTALLMODE来覆盖它。

这可以通过覆盖主wix文件的product部分中的相应属性来实现降级来实现

<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"/>
...