【问题标题】:Wix installer does not overwrite previous version of an executableWix 安装程序不会覆盖以前版本的可执行文件
【发布时间】:2015-04-25 19:55:34
【问题描述】:

我有一个非常简单的安装程序 - 将单个 dll 复制到 Program Files 子文件夹并使用 regsvr32.exe 注册它。效果很好,但如果安装了旧版本的 dll,“修复”不会覆盖现有的 dll。 dll 已签名,其版本(内部版本)编号始终递增(例如 2.0.0.123 - > 2.0.0.124)。

查看之前的类似帖子,我添加了 RemoveExistingProducts 并将 ProductId 指定为“*”。卸载然后安装较新版本的工作正常,但我确实需要修复来更新现有的 dll。

我还有什么需要做的吗?

谢谢!

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

  <!--
When creating a new install for the next version, these fields must be modified
-->
  <?define ProductVersion = "2.0.00" ?>

  <?define ProductId64 = "*" ?>
  <?define ProductId32 = "*" ?>

  <?define PackageId   = "45F34788-66AC-441C-B666-707FFA7F1EE9" ?>


  <!-- Product name as you want it to appear in Add/Remove Programs-->
  <?if $(var.Platform) = x64 ?>
  <?define ProductName = "XYZ (64 bit)" ?>
  <?define Win64 = "yes" ?>
  <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
  <?define ProductId = "$(var.ProductId64)" ?>
  <?define MainDllName = "XYZ64.dll" ?>
  <?define MainDllSource = "..\..\bin\Win64\Release\XYZ64.dll" ?>
  <?else ?>
  <?define ProductName = "XYZ (32 bit)" ?>
  <?define Win64 = "no" ?>
  <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
  <?define ProductId = "$(var.ProductId32)" ?>
  <?define MainDllName = "XYZ.dll" ?>
  <?define MainDllSource = "..\..\bin\Win32\Release\XYZ.dll" ?>
  <?endif ?>


  <?define UpgradeCode = "{C3763742-7C1C-4AB7-A404-F030B7550E97}" ?>


  <Product Id="$(var.ProductId)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="Advanced Messaging Systems LLC" UpgradeCode="$(var.UpgradeCode)">

    <Package Id="$(var.PackageId)" InstallerVersion="200" Compressed="yes" Description="XYZ Installer package"  InstallPrivileges="elevated"/>

    <!-- No restore point  -->
    <Property Id="MSIFASTINSTALL" Value="3" />

   <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="XYZ">

          <Component Id="XYZDll" Guid="E2CBEE41-6C0E-4A84-95C1-7282747B4A3D">
            <File Id='MainDll' Name="$(var.MainDllName)" DiskId='1' Source="$(var.MainDllSource)" SelfRegCost="0" />

            <!-- TODO: Insert files, registry keys, and other resources here. -->
          </Component>

        </Directory>
      </Directory>
    </Directory>

    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />

    <!-- Note: Custom actions to install/uninstall the dll using regsvr32.exe -->
    <CustomAction Id="RegisterDll"
                      Directory="INSTALLLOCATION"
                      ExeCommand='regsvr32.exe /s "[INSTALLLOCATION]$(var.MainDllName)"'

                      Return="check">
    </CustomAction>
    <CustomAction Id="UnregisterDll"
                  Directory="INSTALLLOCATION"
                  ExeCommand='regsvr32.exe /s /u "[INSTALLLOCATION]$(var.MainDllName)"'>
    </CustomAction>


    <Feature Id="ProductFeature" Title="XYZ" Level="1">
      <ComponentRef Id="XYZDll" />
      <!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->
      <ComponentGroupRef Id="Product.Generated" />
    </Feature>

    <InstallUISequence>
      <Custom Action="WixCloseApplications" Before="AppSearch"/>
    </InstallUISequence>

    <InstallExecuteSequence>

      <!-- Uninstall previous version before installing this one. -->
      <RemoveExistingProducts Before="InstallInitialize"/>


      <SelfRegModules/>
    </InstallExecuteSequence>

    <Icon Id="XYZ.ico" SourceFile="..\Graphics\XYZ.ico"/>
    <Property Id="ARPPRODUCTICON" Value="XYZ.ico" />

    <!-- UI -->
    <UIRef Id="WixUI_InstallDir"/>
    <UIRef Id="WixUI_ErrorProgressText" />

    <WixVariable Id="WixUILicenseRtf" Value="..\EULA\license.rtf" />
    <WixVariable Id="WixUIBannerBmp"  Value="..\Graphics\banner.jpg" />
    <WixVariable Id="WixUIDialogBmp"  Value="..\Graphics\logo.jpg" />


    <!-- End UI -->
  </Product>
</Wix>

更新。修改升级条目后,以下内容对我有用:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

  <!--
When creating a new install for the next version, these fields must be modified
-->
  <?define ProductVersion = "2.0.4" ?>

  <?define ProductId64 = "*" ?>
  <?define ProductId32 = "*" ?>

  <?define PackageId   = "*" ?>


  <!-- Product name as you want it to appear in Add/Remove Programs-->
  <?if $(var.Platform) = x64 ?>
  <?define ProductName = "XYZ (64 bit)" ?>
  <?define Win64 = "yes" ?>
  <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
  <?define ProductId = "$(var.ProductId64)" ?>
  <?define MainDllName = "XYZ64.dll" ?>
  <?define MainDllSource = "..\..\bin\Win64\Release\XYZ64.dll" ?>
  <?else ?>
  <?define ProductName = "XYZ (32 bit)" ?>
  <?define Win64 = "no" ?>
  <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
  <?define ProductId = "$(var.ProductId32)" ?>
  <?define MainDllName = "XYZ.dll" ?>
  <?define MainDllSource = "..\..\bin\Win32\Release\XYZ.dll" ?>
  <?endif ?>


  <?define UpgradeCode = "{C3763742-7C1C-4AB7-A404-F030B7550E97}" ?>


  <Product
    Id="$(var.ProductId)"
    Name="$(var.ProductName)"
    Language="1033"
    Version="$(var.ProductVersion)"
    Manufacturer="Advanced Messaging Systems LLC"
    UpgradeCode="$(var.UpgradeCode)"
    >

    <Package Id="$(var.PackageId)"
             InstallerVersion="200"
             Compressed="yes"
             Description="XYZ Installer package"
             InstallPrivileges="elevated"
     />

    <!-- No restore point  -->
    <Property Id="MSIFASTINSTALL" Value="3" />


    <Upgrade Id="$(var.UpgradeCode)">
      <UpgradeVersion Minimum="1.0.0"
                      IncludeMinimum="yes"
                      OnlyDetect="no"
                      Maximum="$(var.ProductVersion)"
                      IncludeMaximum="no"
                      Property="PREVIOUSFOUND" />
    </Upgrade>


    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="XYZ">

          <Component Id="XYZDll" Guid="E2CBEE41-6C0E-4A84-95C1-7282747B4A3D">
            <File Id='MainDll' Name="$(var.MainDllName)" DiskId='1' Source="$(var.MainDllSource)" SelfRegCost="0" />

            <!-- TODO: Insert files, registry keys, and other resources here. -->
          </Component>

        </Directory>
      </Directory>
    </Directory>

    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />

    <!-- Note: Custom actions to install/uninstall the dll using regsvr32.exe -->
    <CustomAction Id="RegisterDll"
                      Directory="INSTALLLOCATION"
                      ExeCommand='regsvr32.exe /s "[INSTALLLOCATION]$(var.MainDllName)"'

                      Return="check">
    </CustomAction>
    <CustomAction Id="UnregisterDll"
                  Directory="INSTALLLOCATION"
                  ExeCommand='regsvr32.exe /s /u "[INSTALLLOCATION]$(var.MainDllName)"'>
    </CustomAction>


    <Feature Id="ProductFeature" Title="XYZ" Level="1">
      <ComponentRef Id="XYZDll" />
      <!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->
      <ComponentGroupRef Id="Product.Generated" />
    </Feature>

    <InstallUISequence>
      <Custom Action="WixCloseApplications" Before="AppSearch"/>
    </InstallUISequence>

    <InstallExecuteSequence>

     <RemoveExistingProducts After="InstallInitialize"/>

      <SelfRegModules/>

    </InstallExecuteSequence>

    <Icon Id="XYZ.ico" SourceFile="..\Graphics\XYZ.ico"/>
    <Property Id="ARPPRODUCTICON" Value="XYZ.ico" />

    <!-- UI -->
    <UIRef Id="WixUI_InstallDir"/>
    <UIRef Id="WixUI_ErrorProgressText" />

    <WixVariable Id="WixUILicenseRtf" Value="..\EULA\license.rtf" />
    <WixVariable Id="WixUIBannerBmp"  Value="..\Graphics\banner.jpg" />
    <WixVariable Id="WixUIDialogBmp"  Value="..\Graphics\logo.jpg" />


    <!-- End UI -->
  </Product>
</Wix>

【问题讨论】:

    标签: wix windows-installer


    【解决方案1】:

    如果您想进行重大升级,请从 WiX MajorUpgrade 元素开始。升级的一般规则是:

    1. ProductCode 和 PackageCode 与旧产品不同。
    2. 在前三个字段的某处增加 ProductVersion。
    3. 与旧产品相同的升级代码。
    4. 做一些事情(如 Wix MajorUprade 或升级元素)以确保您已进行升级。
    5. 按用户安装不会升级按系统安装,反之亦然。

    在您原来的情况下,未能遵循规则 1 和 2 意味着 Windows 认为已安装相同的产品并进入修复模式。这应该是您的第一个警告,因为重大升级看起来像是全新安装,而不是修复。如果您在 Programs&Features 中有两个条目,则意味着未满足这 4 个要求中的一个或多个。如果您收到“已安装此产品的另一个版本”,则表示您没有遵循规则 1,并且与已安装产品相比,行为变化与 ProductCode 和 PackageCode 值有关。

    【讨论】:

    • 对我来说,这是第二点。前三个字段中的产品版本未更改。 joshstechnij 在此线程上也有相同的说明。 community.flexerasoftware.com/archive/index.php?t-197700.html
    • 我假设在您的规则 1 中,ProductCode 应该是 Product Id,PackageCode 应该是 Package Id。它们都应该是"*" 并且是自动生成的。
    【解决方案2】:

    我很惊讶 Wix compilerlinker 允许这条线:

     <?define PackageId   = "45F34788-66AC-441C-B666-707FFA7F1EE9" ?>
    

    如果这确实有效并且通过了,我没有测试过,这意味着你的包有一个硬编码包ID。我认为 Wix 具有针对此问题的保护功能?也许确实如此?如果允许硬编码的包 guid 是否有意义,我们应该与 Wix 社区核实。我想这对于调试和测试目的可能是必要的 - 但至少应该有一个编译器警告。

    包 GUID 的想法是它对于每个编译的 MSI 文件应该是唯一的。它只是用来唯一标识一个文件。 Windows Installer 将根据定义将具有相同包 guid 的两个不同 MSI 文件视为同一个文件。各种 x 文件问题的结果。因此,包 GUID 应该始终自动生成,因为它应该是唯一的。请先尝试解决此问题,以检查这是否解决了您的整体问题。将其设置为 *。

    我的建议是自动生成 package idproduct id,但是设置一个硬编码的升级代码。升级代码标识“产品系列”,可用于标识您的产品的任何实例,无论语言和版本如何。为您的 64 位和 32 位设置使用单独的升级代码可能会很有用,因为这两个版本可以同时安装在某些系统上。

    您可能还希望不再使用 regsvr32.exe 进行自我注册,并从 dll 中提取 COM 数据以获得适当的 MSI 支持:MSI register dll - Self-Registration considered harmful。也许还可以检查一下:Register ActiveX exe server using WiX(如果 Heat 不起作用,请查看 RegSpy2)。

    还要注意 you can leave out a lot of source attributes from your Wix xml file 并依赖 Wix 默认值而不是硬编码值。

    有关 GUID 和文件替换的更多详细信息:

    【讨论】:

    • 我使用 regsvr32.exe 安装 dll,因为 dll 的 DllRegisterServer / DllUnregisterServer 实现足够智能 - 它知道如何在有限权限的环境中工作并将自己安装在 HKCU 而不是 HKLM 中。
    【解决方案3】:

    简短的回答(另一个变得太乱了):尝试删除这一行并通过将包 ID 设置为“*”来自动生成包 ID:

     <?define PackageId   = "45F34788-66AC-441C-B666-707FFA7F1EE9" ?>
    

    请注意,您必须在卸载所有以前的 MSI 版本后停止使用它们。这是由于错误的硬编码包 guid 可能导致不可预知和不可预见的问题。

    【讨论】:

    • 如果 PackageId 为“*”,我的安装程序现在会覆盖旧文件,但它始终作为新安装运行,因此没有修复和卸载按钮,并且“程序和功能”中有多个条目.
    • 如果我对 ProductId guid 进行硬编码,我会收到“已安装此产品的另一个版本”错误提示我先将其删除...
    • 正如 Phil 指出的那样,您现在有一个重大升级可以解决这些问题。这里是some suggested resources for getting familiar with Wix
    猜你喜欢
    • 2016-10-22
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多