无法删除其他安装程序安装的文件

Posted

技术标签:

【中文标题】无法删除其他安装程序安装的文件【英文标题】:Can't remove file installed by another installer 【发布时间】:2013-04-12 13:17:10 【问题描述】:

我想:

    创建一个目录。 运行另一个安装程序(不是 MSI),将一些文件从第 1 点安装到目录中。 替换第 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:

验证ProductID 700 CostInitialize 800 文件成本 900 CostFinalize 1000 InstallValidate 1400 InstallInitialize 1500 Assign_SUBDIRECTORYPROPERTY 1501 流程组件 1600 取消发布功能 1800 RemoveRegistryValues 2600 删除快捷方式 3200 创建文件夹 3700 LaunchWiseInstallation 3701 删除文件 3720 删除文件夹 3730 安装文件 4000 创建快捷方式 4500 WriteRegistryValues 5000 注册用户6000 注册产品 6100 发布功能 6300 发布产品 6400 InstallFinalize 6600

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

抱歉,Rob,但我想你有点误解了我的意思。我自己探索了这个问题并找到了解决方案。我发布了一个关于它的答案。请您检查一下我的详细信息是否正确? 我在您的问题中没有看到任何关于必须从磁盘中删除任意文件的内容。您的回答不正确,我留下了一条评论,指出如果您只想删除一堆文件,RemoveFile 元素将起作用。您可以尝试澄清一下问题以获得更好的答案。 为了清楚起见,我更改了我的问题。我还删除了编码的自定义操作,只使用了 RemoveFile 元素。要对任意文件(以及由另一个安装程序安装的文件)执行此操作,我应该使用 RemoveFile 元素的 Property 属性,如果我是对的,我应该为这个属性分配要删除的文件的相应目录。 【参考方案2】:

首先,我意识到 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 数据库中提到的文件 - 不能用于随机文件。所以在这种情况下它是没有用的。

【讨论】:

RemoveFile 元素可以从磁盘上的任何位置删除文件。此处不需要自定义操作。

以上是关于无法删除其他安装程序安装的文件的主要内容,如果未能解决你的问题,请参考以下文章

无法删除 HSQLDB 文件

inventor2019卸载之后无法再次安装

为我的应用程序运行 Wix 安装程序后,即使在删除文件夹后也无法创建/写入文件/文件夹

TestFlight 安装应用失败,无法删除部分安装的应用

有一个文件无法删除,说是被另一个程序使用。怎么办?

[转]NSIS 制作安装包无法创建桌面快捷方式或无法删除开始菜单项