1

我想要:

  1. 创建一个目录。
  2. 运行另一个安装程序(不是 MSI),将一些文件从第 1 点安装到目录中。
  3. 替换在第 2 点安装的一些文件。

所有这些都必须在我在 WiX(Windows Installer XML)的帮助下创建的安装下完成。

下面是我的 WiX 文件的一个重要部分。问题是这个安装不会像我想要的那样替换文件。要删除文件,我使用带有 Property 属性的 RemoveFile 元素,因为它是删除不在安装程序数据库中的文件的唯一方法(除了在自定义操作中编写代码 - 这是我不想要的)。

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="ProgramFilesFolder">
        <Directory Id="ManufacturerDirectory" Name="$(var.Manufacturer)">
            <Directory Id="ProductDirectory" Name="$(var.ProductName)">
                <Directory Id="SubDirectory" Name="$(var.SubDirectoryName)">
                </Directory>
            </Directory>
        </Directory>
    </Directory>
</Directory>

<!-- Create the directory at point 1. -->
<Component
    Id="RemoveOldData" Guid="..."   KeyPath="yes" 
    Directory="ManufacturerDirectory">
    <CreateFolder Directory="ProductDirectory" />
</Component>

<!-- Following two components replace the file(s) (point 3). -->

<Component
    Id="RemoveOldData" Guid="..."
    Directory="SubDirectory" KeyPath="yes"      
    >   
    <RemoveFile 
        Id="Remove_MyFile.exe" On="install"
        Property="SUBDIRECTORYPROPERTY" Name="MyFile.exe" />
</Component>

<Component
    Id="FilesToReplace" Guid="..."
    Directory="SubDirectory">
    <File 
        Id="MyFile.exe" Vital="yes" KeyPath="yes" DiskId="1"        
        Source="$(var.SourcePath)MyFile.exe" Name="MyFile.exe"
        />
</Component>

<Binary Id="WiseInstallation" SourceFile="$(var.WiseSourcePath)..." />

<!-- Launch Wise installation at point 2. -->
<CustomAction
    Id="LaunchWiseInstallation"
    BinaryKey="WiseInstallation"
    ExeCommand=""
    Return="check"
    Execute="deferred"
    Impersonate="yes" />

<!-- Following custom action assigns a property.
This needs to remove files that are not in the current installer database.
To do it, the Property attribute of the RemoveFile element is needed. -->   
<CustomAction
    Id="Assign_SUBDIRECTORYPROPERTY"
    Property="SUBDIRECTORYPROPERTY"
    Value="[SubDirectory]" />

<InstallExecuteSequence>
    <Custom Action="Assign_SUBDIRECTORYPROPERTY" After="InstallInitialize" >
        NOT Installed</Custom>
    <Custom Action="LaunchWiseInstallation" After="CreateFolders" >
        NOT Installed</Custom>
    <RemoveFiles Sequence="3720"/>
    <RemoveFolders Sequence="3730"/>
</InstallExecuteSequence>

从 Orca 的角度来看 InstallExecuteSequence:

  • 验证产品 ID 700
  • 成本初始化 800
  • 文件成本 900
  • 成本最终确定 1000
  • 安装验证 1400
  • 安装初始化 1500
  • 分配_SUBDIRECTORYPROPERTY 1501
  • 过程组件 1600
  • 取消发布功能 1800
  • 删除注册表值 2600
  • 删除快捷方式 3200
  • 创建文件夹 3700
  • LaunchWise 安装 3701
  • 删除文件 3720
  • 删除文件夹 3730
  • 安装文件 4000
  • 创建快捷方式 4500
  • 写入注册表值 5000
  • 注册用户 6000
  • 注册产品 6100
  • 发布功能 6300
  • 发布产品 6400
  • 安装完成 6600

我还检查了安装日志文件:

  • SUBDIRECTORYPROPERTY 属性分配得当;
  • 正确遵循了 InstallExecuteSequence;
  • 安装完成,没有错误。

但是这些文件从未被删除或替换!

4

2 回答 2

1

首先,一个 MSI 不能安装另一个 MSI,所以 #2 中的安装包不能是一个 MSI。如果不是,则安排启动其他安装包的自定义操作,如下所示:

<InstallExecuteSequence>
   <Custom Action='LaunchOtherInstaller' After='CreateFolders' />
</InstallExecuteSequence>

CreateFolders操作发生在InstallFiles操作之前,因此您的安装程序应该能够在两者之间跳转。

于 2013-04-13T03:52:53.303 回答
0

首先,我意识到 MSI 不能直接删除由另一个安装程序(MSI 与否)安装的文件 - 它仅适用于安装过程中其数据库中提到的文件(即由它自己或以前版本安装的文件) )。但是通过自定义操作可以。因此,如果没有自定义操作,就无法实现第 3 点。所以正确的顺序可以是这样的:

<InstallExecuteSequence>
  <Custom 
    Action="LaunchWiseInstallation" 
    After="CreateFolders" 
    >
    NOT Installed
    </Custom>
  <Custom 
    Action="DeleteOldData" 
    After="LaunchWiseInstallation" 
    >
    NOT Installed
    </Custom>
</InstallExecuteSequence>

其中 DeleteOldData 是一个 CustomAction 元素,它指向包含实际删除文件的自定义操作的 DLL 或 .exe。只能提到,也许 DeleteOldData 自定义操作应该具有 Execute="deferred" 属性以在脚本中运行,并且应该具有 Impersonate="yes" 属性以避免 UAC 限制和文件访问。如果安装程序由具有高于 LocalSystem 预先设置的管理权限的用户运行,则后者是正确的。

并且 RemoveFile 标签只能与 MSI 数据库中提到的文件一起使用 - 而不是随机文件。所以在这种情况下是没有用的。

于 2013-04-25T13:33:41.277 回答