无法删除文件夹 WIX 安装程序

Can't delete folder WIX installer

我有一个由我的 WIX 安装程序安装的服务:

<Component Id="cmp_myService" Guid="{5FC8815E-33T8-4C3D-9654-849EE4CB1E22}">
    <File Id="f_myService" Name="MyService.exe" Source="$(var.SourcePath)MyService.exe" KeyPath="yes" />
    <ServiceInstall Id="si_myServiceInstall" Name="My Service" DisplayName="It is my service" Type="ownProcess" Interactive="yes" Start="auto" ErrorControl="normal" Description="Here is some description" />
    <ServiceControl Id="sc_startStopMyService" Name="My Service" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
</Component>

另外,我有一个自定义操作 ca1_removeInstallDirOnUnsinstall 可以删除一个文件夹及其所有内容(MyService.exe 在这个文件夹中)

<Custom Action="ca1_removeInstallDirOnUnsinstall" After="DeleteServices"><![CDATA[REMOVE="ALL"]]></Custom>

我将此自定义操作安排到 运行,紧接在执行顺序中的 DeleteServices 操作之后。我假设此时 MyService.exe 应该停止并删除。但是我得到一个异常 Access to the path 'MyService.exe' is denied ,这意味着该服务尚未删除。为什么会发生这种情况,我的自定义操作应该安排在哪里以确保服务已被删除?

相关日志文件:

MSI (s) (64:3C) [08:42:32:597]: Doing action: StopServices
MSI (s) (64:3C) [08:42:32:597]: Note: 1: 2205 2:  3: ActionText 
Action ended 8:42:32: UnpublishFeatures. Return value 1.
Action start 8:42:32: StopServices.
MSI (s) (64:3C) [08:42:32:597]: Doing action: DeleteServices
MSI (s) (64:3C) [08:42:32:597]: Note: 1: 2205 2:  3: ActionText 
Action ended 8:42:32: StopServices. Return value 1.
Action start 8:42:32: DeleteServices.
MSI (s) (64:3C) [08:42:32:597]: Doing action: ca1_removeInstallDirOnUnsinstall
MSI (s) (64:3C) [08:42:32:597]: Note: 1: 2205 2:  3: ActionText 
Action ended 8:42:32: DeleteServices. Return value 1.
MSI (s) (64:80) [08:42:32:597]: Invoking remote custom action. DLL: C:\windows\Installer\MSIA125.tmp, Entrypoint: RemoveInstallDirRecursively
MSI (s) (64:B8) [08:42:32:597]: Generating random cookie.
MSI (s) (64:B8) [08:42:32:597]: Created Custom Action Server with PID 6176 (0x1820).
MSI (s) (64:98) [08:42:32:644]: Running as a service.
MSI (s) (64:B4) [08:42:32:644]: Hello, I'm your 32bit Impersonated custom action server.
Action start 8:42:32: ca1_removeInstallDirOnUnsinstall.
SFXCA: Extracting custom action to temporary directory: C:\windows\Installer\MSIA125.tmp-\
SFXCA: Binding to CLR version v4.0.30319
Calling custom action CustomAction!CustomAction.FilesAndFoldersCustomAction.RemoveInstallDirRecursively
Access to the path 'MyService.exe' is denied.

InstallFinalizeDeleteServices发生在[之前=11=]。我想 msiexec.exe 可能会在文件夹上锁定,以便在重大升级过程中重新安装,但我不确定(查找锁定使用:perfmon.exe, procexp64.exe).您可以将删除操作放在 InstallFinalize 之前(结束更改系统的提升操作)。这个位置应该有效,但不能保证。 “核对”整个文件夹不是好的做法。

最佳实践:通常你不应该删除整个文件夹(这是相当危险的 - 搞砸了,你最终可能会删除一半的计算机。说真的。我已经看到它发生了。不是用 MSI,而是用“清理 EXE”)。我会将日志文件放在用户配置文件或 %ProgramFiles% 之外的其他位置。或者可以使用 event log 甚至数据库上传到网上,以避免留下太多文件。

可接受的残留物:在我看来,不应尝试自动卸载日志文件和其他用户数据。为什么?它们是用户数据——换句话说:它们属于用户。你不能草率地删除它们吗?我会把数据留在原地,以防他们想要分析它们或重新安装应用程序(后者对于许可证密钥特别重要 - 你会留下它们吗?)。

WiX:WiX 有几个内置结构来帮助删除文件和文件夹。有内置的 MSI 变体(RemoveFile, RemoveFolder) that just delete files by wildcard or name. Then there is the RemoveFileEx described by Bob Arnson (WiX developer team)。请阅读博客 post。我相信它可以递归地完成这项工作(所有子文件夹)。如你所知,我不经常使用这些结构因为我喜欢其他清理方法。坦率地说,我只是尝试在 PDF 或在线 KDB 文章中记录清理过程。


链接:

  • wix - how to delete non-empty folder
  • WIX - How to use RemoveFiles