卸载WiX时删除文件

pri*_*iro 77 installer windows-installer custom-action wix

卸载我的应用程序时,我想配置Wix设置以删除原始安装后添加的所有文件.看起来卸载程序只删除了最初从MSI文件安装的目录和文件,并且它保留了稍后在应用程序文件夹中添加的所有其他内容.换句话说,我想在卸载时清除目录.我怎么做?

Pav*_*uva 81

使用RemoveFile元素和On =" uninstall ".这是一个例子:

<Directory Id="CommonAppDataFolder" Name="CommonAppDataFolder">
  <Directory Id="MyAppFolder" Name="My">
    <Component Id="MyAppFolder" Guid="*">
      <CreateFolder />
      <RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
    </Component>
  </Directory>
</Directory>
Run Code Online (Sandbox Code Playgroud)

更新

它不起作用100%.它删除了文件,但没有删除任何其他目录 - 安装后创建的目录.有什么想法吗? - pribeiro

遗憾的是,Windows Installer不支持使用子目录删除目录.在这种情况下,您必须采取自定义操作.或者,如果您知道子文件夹是什么,请创建一堆RemoveFolder和RemoveFile元素.

  • 我更新了我的答案来解决你的问题. (2认同)
  • @PhilipRego有关CommonAppDataFolder文档,请参阅https://msdn.microsoft.com/en-us/library/windows/desktop/aa367992.aspx. (2认同)

Ale*_*nov 29

RemoveFolderEx在WiX中使用Util扩展中的元素.
使用此方法,还会删除所有子目录(而不是直接使用RemoveFile元素).此元素在MSI数据库中添加临时行RemoveFileRemoveFolder表.

  • 警告:当使用 RemoveFolderEx on="uninstall" 时,它还会在升级 (Wix 3.9) 时删除文件夹。`RemoveFile` 和 `RemoveFolder` 上的行为相同。如果您想在升级时保留文件,则不能使用所有这些方法。 (2认同)

Fri*_*rge 12

为此,我只是创建了一个在卸载时调用的自定义操作.

WiX代码如下所示:

<Binary Id="InstallUtil" src="InstallUtilLib.dll" />

<CustomAction Id="DIRCA_TARGETDIR" Return="check" Execute="firstSequence" Property="TARGETDIR" Value="[ProgramFilesFolder][Manufacturer]\[ProductName]" />
<CustomAction Id="Uninstall" BinaryKey="InstallUtil" DllEntry="ManagedInstall" Execute="deferred" />
<CustomAction Id="UninstallSetProp" Property="Uninstall" Value="/installtype=notransaction /action=uninstall /LogFile= /targetDir=&quot;[TARGETDIR]\Bin&quot; &quot;[#InstallerCustomActionsDLL]&quot; &quot;[#InstallerCustomActionsDLLCONFIG]&quot;" />

<Directory Id="BinFolder" Name="Bin" >
    <Component Id="InstallerCustomActions" Guid="*">
        <File Id="InstallerCustomActionsDLL" Name="SetupCA.dll" LongName="InstallerCustomActions.dll" src="InstallerCustomActions.dll" Vital="yes" KeyPath="yes" DiskId="1" Compressed="no" />
        <File Id="InstallerCustomActionsDLLCONFIG" Name="SetupCA.con" LongName="InstallerCustomActions.dll.Config" src="InstallerCustomActions.dll.Config" Vital="yes" DiskId="1" />
    </Component>
</Directory>

<Feature Id="Complete" Level="1" ConfigurableDirectory="TARGETDIR">
    <ComponentRef Id="InstallerCustomActions" />
</Feature>

<InstallExecuteSequence>
    <Custom Action="UninstallSetProp" After="MsiUnpublishAssemblies">$InstallerCustomActions=2</Custom>
    <Custom Action="Uninstall" After="UninstallSetProp">$InstallerCustomActions=2</Custom>
</InstallExecuteSequence>
Run Code Online (Sandbox Code Playgroud)

InstallerCustomActions.DLL中的OnBeforeUninstall方法的代码如下所示(在VB中).

Protected Overrides Sub OnBeforeUninstall(ByVal savedState As System.Collections.IDictionary)
    MyBase.OnBeforeUninstall(savedState)

    Try
        Dim CommonAppData As String = Me.Context.Parameters("CommonAppData")
        If CommonAppData.StartsWith("\") And Not CommonAppData.StartsWith("\\") Then
            CommonAppData = "\" + CommonAppData
        End If
        Dim targetDir As String = Me.Context.Parameters("targetDir")
        If targetDir.StartsWith("\") And Not targetDir.StartsWith("\\") Then
            targetDir = "\" + targetDir
        End If

        DeleteFile("<filename.extension>", targetDir) 'delete from bin directory
        DeleteDirectory("*.*", "<DirectoryName>") 'delete any extra directories created by program
    Catch
    End Try
End Sub

Private Sub DeleteFile(ByVal searchPattern As String, ByVal deleteDir As String)
    Try
        For Each fileName As String In Directory.GetFiles(deleteDir, searchPattern)
            File.Delete(fileName)
        Next
    Catch
    End Try
End Sub

Private Sub DeleteDirectory(ByVal searchPattern As String, ByVal deleteDir As String)
    Try
        For Each dirName As String In Directory.GetDirectories(deleteDir, searchPattern)
            Directory.Delete(dirName)
        Next
    Catch
    End Try
End Sub
Run Code Online (Sandbox Code Playgroud)


Pie*_*rre 9

这是@ tronda建议的变体.我正在删除在卸载期间由另一个自定义操作创建的文件"install.log":

<Product>
    <CustomAction Id="Cleanup_logfile" Directory="INSTALLFOLDER"
    ExeCommand="cmd /C &quot;del install.log&quot;"
    Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />

    <InstallExecuteSequence>
      <Custom Action="Cleanup_logfile" Before="RemoveFiles" >
        REMOVE="ALL"
      </Custom>
    </InstallExecuteSequence>
</Product>
Run Code Online (Sandbox Code Playgroud)

据我所知,我不能使用"RemoveFile",因为此文件是在安装后创建的,并且不是组件组的一部分.

  • 我确实使用了这个解决方案,通过一些更改来删除整个目录:ExeCommand ="cmd/C RD"[INSTALLFOLDER]&quot;/s/q" (3认同)

tro*_*nda 7

不是WIX专家,但可能(更简单?)解决方案是运行Quiet Execution Custom Action,它是WIX内置扩展的一部分吗?

可以使用/ S和/ Q选项运行rmdir MS DOS命令.

<Binary Id="CommandPrompt" SourceFile="C:\Windows\System32\cmd.exe" />
Run Code Online (Sandbox Code Playgroud)

完成工作的自定义操作很简单:

<CustomAction Id="DeleteFolder" BinaryKey="CommandPrompt" 
              ExeCommand='/c rmdir /S /Q "[CommonAppDataFolder]MyAppFolder\PurgeAppFolder"' 
              Execute="immediate" Return="check" />
Run Code Online (Sandbox Code Playgroud)

然后你必须修改InstallExecuteSequence,如许多地方所记录的那样.

更新: 有这种方法的问题.结束了定制任务,但仍然认为这是一个可行的解决方案,但没有让细节工作.

  • 不要这样做.1)您将`cmd.exe`嵌入到安装程序中.2)您在脚本生成期间对系统进行了更改3)没有回滚选项4)不正确处理锁定文件 (4认同)

Eli*_*Eli 5

对于@Pavel建议,这将是一个更完整的答案,对我而言,它正在100%起作用:

<Fragment Id="FolderUninstall">
    <?define RegDir="SYSTEM\ControlSet001\services\[Manufacturer]:[ProductName]"?>
    <?define RegValueName="InstallDir"?>
    <Property Id="INSTALLFOLDER">
        <RegistrySearch Root="HKLM" Key="$(var.RegDir)" Type="raw" 
                  Id="APPLICATIONFOLDER_REGSEARCH" Name="$(var.RegValueName)" />
    </Property>

    <DirectoryRef Id='INSTALLFOLDER'>
        <Component Id="UninstallFolder" Guid="*">
            <CreateFolder Directory="INSTALLFOLDER"/>
            <util:RemoveFolderEx Property="INSTALLFOLDER" On="uninstall"/>
            <RemoveFolder Id="INSTALLFOLDER" On="uninstall"/>
            <RegistryValue Root="HKLM" Key="$(var.RegDir)" Name="$(var.RegValueName)" 
                    Type="string" Value="[INSTALLFOLDER]" KeyPath="yes"/>
        </Component>
    </DirectoryRef>
</Fragment>
Run Code Online (Sandbox Code Playgroud)

并且,在“产品”元素下:

<Feature Id="Uninstall">
    <ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>
Run Code Online (Sandbox Code Playgroud)

此方法使用卸载时要删除的文件夹的所需路径设置注册表值。最后,INSTALLFOLDER和注册表文件夹都从系统中删除。请注意,注册表的路径可以在其他配置单元和其他位置。