【问题标题】:Wix remove appdata folder on uninstallWix 在卸载时删除 appdata 文件夹
【发布时间】:2016-05-13 23:33:08
【问题描述】:

我正在使用 Wix 3.11 并尝试了许多不同的方式和方法,但似乎无法弄清楚为什么 Wix 没有删除我的 ApplicationDataFolder 文件夹。在安装期间,我在 ApplicationDataFolder 位置为用户创建文件夹。

我的应用程序使用日志记录并将其与其他一些内容一起存储在目录中。在卸载期间,应用程序文件夹中的所有内容都将被删除,但包含日志和其他文件的 appdata 文件夹保持不变。

我不知道为什么或我错过了什么。

WXS 模板

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
  <Product Id="*" UpgradeCode="9e578e3d-0119-425c-8633-f54ffaaa4929" Name="@product.name@" Version="@product.version@" Manufacturer="@product.company@" Language="1033">
    <Package InstallerVersion="400" Compressed="yes" InstallScope="perMachine" Comments="@product.version@" Description="@product.description@"/>
    <Media Id="1" Cabinet="SomeApp.cab" EmbedCab="yes" />

    <!-- Installer Properties -->
    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
    <PropertyRef Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED"/>

    <!-- Installer Resources -->
    <Icon Id="ApplicationIcon" SourceFile="SomeApp 4\SomeApp 4_vista.ico"/>
    <Property Id="ARPPRODUCTICON" Value="ApplicationIcon" />

    <Property Id="INSTALLDIR">
        <RegistrySearch Key="SOFTWARE\Acme\SomeApp" 
                        Root="HKCU" Type="raw" 
                        Id="APPLICATIONFOLDER_REGSEARCH" Name="installation-path" />
    </Property>

    <WixVariable Id="WixUILicenseRtf" Value="SomeApp 4\license.rtf" />
    <WixVariable Id="WixUIBannerBmp" Value="WixUIBannerBmp.bmp" />
    <WixVariable Id="WixUIDialogBmp" Value="WixUIDialogBmp.bmp" />

    <!-- Check Existing Install -->
    <Upgrade Id="9e578e3d-0119-425c-8633-f54ffaaa4929">
        <UpgradeVersion Minimum="@product.version@" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
        <UpgradeVersion Minimum="0.0.0" Maximum="@product.version@" IncludeMinimum="yes" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED"/>   
    </Upgrade>
    <Condition Message="A newer version of this software is already installed.">NOT NEWERVERSIONDETECTED</Condition>

    <!-- Prerequisites -->
    <Condition Message="This application requires .NET Framework 4.6 or newer. Please install the .NET Framework then run this installer again.">
      <![CDATA[Installed OR WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED]]>
    </Condition>

    <Condition Message="This application requires at least Windows 7 or Windows Server 2008 R2. Please upgrade your computer to a supported operating system and run this installer again.">
      <![CDATA[Installed OR (VersionNT >= 601)]]>
    </Condition>

    <!-- Define the directory structure -->
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder" Name="ProgramFiles">
        <Directory Id="INSTALLDIR" Name="@product.company@">
            @product.applicationfiles@
            @product.servicefiles@
        </Directory>
      </Directory>
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ApplicationProgramsFolder" Name="@product.name@"/>
        <Directory Id="ServiceProgramsFolder" Name="@product.name@"/>
      </Directory>
      <Directory Id="DesktopFolder" Name="Desktop" /> 
      <Directory Id="LocalAppDataFolder">
        <Directory Id="ApplicationDataFolder" Name="Acme" />
      </Directory>            
    </Directory>

    <DirectoryRef Id="ApplicationProgramsFolder">
        <Component Id="ApplicationShortcut" Guid="1e578e4d-0229-425c-8633-f54ffaaa4901">
            <Shortcut Id="ApplicationStartMenuShortcut" 
                Name="SomeApp 4.6" 
                Description="@product.company@ @product.name@ @product.version@"
                Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe"
                WorkingDirectory="INSTALLDIR"
                Icon ="ApplicationIcon"/>       
            <Shortcut Id="ApplicationStartMenuShortcut2" 
                Name="SomeApp 4.6 (Multiple Instances)" 
                Description="@product.company@ @product.name@ @product.version@"
                Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe"
                Arguments="MultipleInstance=True"
                WorkingDirectory="INSTALLDIR"
                Icon ="ApplicationIcon"/>  
            <Shortcut Id="ApplicationStartMenuShortcut3" 
                Name="SomeApp 4.6 (Notifications)" 
                Description="@product.company@ @product.name@ @product.version@"
                Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe"
                Arguments="Notifications=True"
                WorkingDirectory="INSTALLDIR"
                Icon ="ApplicationIcon"/>                   
            <Shortcut Id="HelpStartMenuShortcut" 
                Name="SomeApp 4.6 Help" 
                Target="[INSTALLDIR]SomeApp 4\Documentation\SomeApp.chm"
                WorkingDirectory="INSTALLDIR"/>                 
            <Shortcut Id="UninstallProduct"             
                      Name="Uninstall SomeApp 4.6"
                      Target="[SystemFolder]msiexec.exe"
                      Arguments="/x [ProductCode]"
                      Description="Uninstall @product" />                    
            <Shortcut Id="desktopshortcut" 
                      Directory="DesktopFolder" 
                      Name="SomeApp 4.6" 
                      WorkingDirectory="INSTALLDIR" 
                      Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe" />
            <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
            <util:RemoveFolderEx On="uninstall" Property="ApplicationDataFolder" />                       
       </Component>
    </DirectoryRef>

    <DirectoryRef Id="ServiceProgramsFolder">
       <Component Id="ServiceShortcut" Guid="9e578e3d-0229-425c-8633-f54ffaaa4901">
            <Shortcut Id="ServiceStartMenuShortcut"
                Name="@product.name@ Reporting Service" 
                Description="@product.name@ Reporting Service"
                Target="[INSTALLDIR]Reporting\SomeApp.ReportingService.exe"
                WorkingDirectory="INSTALLDIR"
                Icon ="ApplicationIcon"/>
            <RemoveFolder Id="ServiceProgramsFolder" On="uninstall"/>                    
            <RegistryValue Root="HKCU" Key="Software\Microsoft\Acme\SomeApp" Name="service-installed" Type="integer" Value="1" KeyPath="yes"/>                   
       </Component>
    </DirectoryRef>   

    <DirectoryRef Id="INSTALLDIR">
        <Component Id="CleanupMainApplicationFolder" Guid="*">
            <RegistryValue Root="HKCU" Key="SOFTWARE\Acme\SomeApp" Name="installation-path" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
            <util:RemoveFolderEx On="uninstall" Property="INSTALLDIR" />                
            <util:RemoveFolderEx On="uninstall" Property="ApplicationDataFolder" />                
        </Component>
    </DirectoryRef>

    <!--  Feature: SomeApp Application -->            
    <Feature Id="Feature.Application"
                     Title="SomeApp 4 - Application"
                     Description="SomeApp is an asset management and maintenance application designed to optimize asset value and improve manufacturing productivity."
                     ConfigurableDirectory="INSTALLDIR"
                     Level="1"
                     AllowAdvertise="no">
                    @product.applicationcomponents@
                    <ComponentRef Id="ApplicationShortcut" />                    
                    <ComponentRef Id="CleanupMainApplicationFolder" />                    
    </Feature>

    <!--  Feature: Reporting Service -->
    <Feature Id="Feature.Service"
                     Title="SomeApp 4 - Reporting Service"
                     Description="This service generates and delivers reports that have been scheduled in the SomeApp Maintenance Management System."
                     ConfigurableDirectory="INSTALLDIR"
                     Level="3"
                     AllowAdvertise="no">
                    @product.servicecomponents@    
                    <ComponentRef Id="ServiceShortcut" />                    
        <Component Id="ReportingServiceInstaller" Guid="B72CAA3F-F2DB-48D2-90DD-061209AB2CE5" Directory="INSTALLDIR">
            <CreateFolder />
            <File Id="ReportingService.exe" Name="ReportingService.exe" KeyPath="yes" Source="@product.sourcedir@\Reporting\SomeApp.ReportingService.exe"/>
            <ServiceInstall Id="ReportingServiceInstaller"
                Type="ownProcess"
                Vital="yes"
                Name="SomeApp Reporting Service"                    
                DisplayName="SomeApp - Reporting Service"
                Description="This service generates and delivers reports that have been scheduled in the SomeApp Maintenance Management System."
                Start="auto"
                Account="NT AUTHORITY\LocalService"
                ErrorControl="ignore"
                Interactive="no" />
        </Component>     

    </Feature>

    <CustomAction Id="Cleanup_logfile" Directory="INSTALLDIR" 
    ExeCommand="cmd /C &quot;rmdir %LOCALAPPDATA%\Acme /s /q&quot;" 
    Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />

    <InstallExecuteSequence>
      <Custom Action="Cleanup_logfile" After="RemoveFiles" >
        REMOVE="ALL" 
      </Custom>
    </InstallExecuteSequence>

    <InstallExecuteSequence>
        <RemoveExistingProducts After="InstallValidate"/>
    </InstallExecuteSequence>   

    <UIRef Id="WixUI_FeatureTree" />
    <UI>
      <DialogRef Id="FilesInUse" />
      <DialogRef Id="MsiRMFilesInUse" />
      <!-- Add the GUI logic for installation -->
    </UI>
  </Product>
</Wix>

【问题讨论】:

    标签: wix windows-installer f#-fake


    【解决方案1】:

    我有一个使用 util:RemoveFolderEx 的项目,它工作正常。我能看到的唯一区别是我在运行时将一个属性显式设置为安装目录的值。我的猜测是“INSTALLDIR”和“ApplicationDataFolder”实际上不是属性,因为它们存储在您的 msi 的目录表中,而不是属性表中。 (使用 ORCA 检查)

    尝试做

    <SetProperty Id='AcmeAppDataFolderToRemove' Value='[ApplicationDataFolder]' After='AppSearch'/>
    

    然后将您的 util:RemoveFolderEx 更改为

    <util:RemoveFolderEx On="uninstall" Property="AcmeAppDataFolderToRemove" />
    

    看看这是否有效。 (您可能需要使用 Value='ApplicationDataFolder' 而没有 [] 不确定。)


    为了响应您的编辑,我查看了 RemoveFolderEx 页面,这看起来很重要

    实现 RemoveFolderEx 的自定义操作通过将临时行写入您指定的根文件夹的每个子文件夹的 RemoveFile 表来实现。因为它可能会极大地影响 Windows Installer 的 File Costing,所以必须在 CostInitialize 标准操作之前写入临时行。不幸的是,MSI 直到稍后在 CostFinalize 操作中才为您的包中的目录层次结构创建属性。

    我认为将其设置为目录会起作用,但是当 RemoveFolderEx 操作实际执行时,这些目录显然还没有值。因此,当它尝试解析属性或设置属性时,它们实际上只是空的。

    所说我的安装程序所做的和它实际所做的不同之处在于我通过 RegistrySearch 获得了我设置属性的值。

    <Property Id="INSTALLDIR">
        <RegistrySearch 
            Id='InstallDirRegistrySearch' 
            Type='raw'
            Root='HKLM' 
            Key='SOFTWARE\$(var.OEMRegistryRootKeyName)' 
            Name='SDKPath' />
    </Property>
    <SetProperty Id='SDKFolderToRemove' Value='[INSTALLDIR]\$(var.OEMProduct) SDK' After='AppSearch'/>
    

    所以我会尝试将 appdata 目录写入注册表项并通过注册表搜索将值放入属性中,然后在您的 removefolderex 中使用该属性,您可能不需要 setproperty,我只是使用它,因为我需要一个INSTALLDIR 下的文件夹,但在您的情况下,您可以将注册表项设置为正确的文件夹。

    【讨论】:

    • 不,文件夹还在。 :(
    • 查看 HR 之后的编辑,似乎目录的值直到 RemoveFolderEx 操作执行后才真正设置,因此它认为属性为空白并且可能什么都不做。
    • 啊,它成功了!你不知道我在解决这个该死的事情上浪费了多少时间。不敢相信它是如此简单。好先生,我向您致敬,谢谢!
    • 是的,很多这些东西看起来很容易修复,但很难理解为什么它不起作用,甚至从哪里开始修复它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 2011-11-23
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    相关资源
    最近更新 更多