使用 WIX 工具集创建的安装包不会在卸载时删除程序文件夹 + 文件

Installation package created with WIX Toolset does not remove program folder + files on uninstallation

我使用 WIX 工具集创建了以下安装例程。 安装按需要进行,但仅卸载 TopShelf 服务。但是,程序文件夹和其中包含的文件仍然存在。缺少什么使得程序文件夹+文件在卸载过程中也被删除?

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*" Name="GC Log Collector Config" Language="1033" Version="1.0.0.0" Manufacturer="xyz" UpgradeCode="ff65ecf3-f59d-4d29-bb3b-ce159892a107">
        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
        <MediaTemplate EmbedCab="yes" />

        <Icon Id="appicon.ico" SourceFile="$(var.GC Log Config.ProjectDir)Resources\gclcc.ico" />
        <Property Id="ARPPRODUCTICON" Value="appicon.ico" />

        <Feature Id="ProductFeature" Title="GC Log Collector Config" Level="1">
            <ComponentRef Id="ProductComponents" />
            <ComponentRef Id="ServiceComponents"/>
            <ComponentGroupRef Id="DllComponents" />
            <ComponentRef Id ="DesktopShortcut"/>
        </Feature>
    </Product>

    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLFOLDER" Name="GC Log Collector Config" />
            </Directory>
            <Directory Id="DesktopFolder" Name="Desktop"/>
        </Directory>

        <CustomAction Id="InstallService" Directory="INSTALLFOLDER" Execute="commit" Return="check" Impersonate="no" ExeCommand="[INSTALLFOLDER]GC Log Collector.exe install"/>
        <CustomAction Id="UninstallService" Directory="INSTALLFOLDER" Execute="commit" Return="check" Impersonate="no" ExeCommand="[INSTALLFOLDER]GC Log Collector.exe uninstall"/>
        
        <InstallExecuteSequence>
            <Custom Action="InstallService" After="InstallFiles">
                NOT Installed
            </Custom>
            <Custom Action="UninstallService" After="InstallInitialize">
                REMOVE ~= "ALL" AND NOT UPGRADINGPRODUCTCODE
            </Custom>
        </InstallExecuteSequence>

        <Component Id="ProductComponents" Directory="INSTALLFOLDER">
            <File Id="GcLogCollectorConfigExe" Source="$(var.GC Log Config.TargetPath)" KeyPath="yes">
            </File>
        </Component>

        <Component Id="ServiceComponents" Directory="INSTALLFOLDER">
            <File Id="GcLogCollectorService" Source="$(var.GC Log Collector.TargetPath)" KeyPath="yes">
            </File>
        </Component>

        <ComponentGroup Id="DllComponents" Directory="INSTALLFOLDER">
            <Component Id="BootstrapIcons">
                <File Id="BootstrapIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.BootstrapIcons.dll"></File>
            </Component>
            <Component Id="BoxIcons">
                <File Id="BoxIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.BoxIcons.dll"></File>
            </Component>
            <Component Id="Codicons">
                <File Id="CodiconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Codicons.dll"></File>
            </Component>
            <Component Id="Core">
                <File Id="CoreDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Core.dll"></File>
            </Component>
            <Component Id="IconPacks">
                <File Id="IconPacksDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.dll"></File>
            </Component>
            <Component Id="Entypo">
                <File Id="EntypoDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Entypo.dll"></File>
            </Component>
            <Component Id="EvaIcons">
                <File Id="EvaIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.EvaIcons.dll"></File>
            </Component>
            <Component Id="FeatherIcons">
                <File Id="FeatherIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.FeatherIcons.dll"></File>
            </Component>
            <Component Id="FileIcons">
                <File Id="FileIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.FileIcons.dll"></File>
            </Component>
            <Component Id="Fontaudio">
                <File Id="FontaudioDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Fontaudio.dll"></File>
            </Component>
            <Component Id="FontAweseome">
                <File Id="FontAwesomeDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.FontAwesome.dll"></File>
            </Component>
            <Component Id="ForkAwesome">
                <File Id="ForkAwesomeDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.ForkAwesome.dll"></File>
            </Component>
            <Component Id="Ionicons">
                <File Id="IoniconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Ionicons.dll"></File>
            </Component>
            <Component Id="JamIcons">
                <File Id="JamIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.JamIcons.dll"></File>
            </Component>
            <Component Id="Material">
                <File Id="MaterialDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Material.dll"></File>
            </Component>
            <Component Id="MaterialDesign">
                <File Id="MaterialDesignDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.MaterialDesign.dll"></File>
            </Component>
            <Component Id="MaterialLight">
                <File Id="MaterialLightDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.MaterialLight.dll"></File>
            </Component>
            <Component Id="Microns">
                <File Id="MicronsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Microns.dll"></File>
            </Component>
            <Component Id="Modern">
                <File Id="ModernDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Modern.dll"></File>
            </Component>
            <Component Id="Octicons">
                <File Id="OcticonsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Octicons.dll"></File>
            </Component>
            <Component Id="PicolIcons">
                <File Id="PicolIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.PicolIcons.dll"></File>
            </Component>
            <Component Id="PixelartIcons">
                <File Id="PixelartIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.PixelartIcons.dll"></File>
            </Component>
            <Component Id="RadixIcons">
                <File Id="RadixIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.RadixIcons.dll"></File>
            </Component>
            <Component Id="RemixIcon">
                <File Id="RemixIconDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.RemixIcon.dll"></File>
            </Component>
            <Component Id="RPGAwesome">
                <File Id="RPGAwesomeDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.RPGAwesome.dll"></File>
            </Component>
            <Component Id="SimpleIcons">
                <File Id="SimpleIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.SimpleIcons.dll"></File>
            </Component>
            <Component Id="Typicons">
                <File Id="TypiconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Typicons.dll"></File>
            </Component>
            <Component Id="Unicons">
                <File Id="UniconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Unicons.dll"></File>
            </Component>
            <Component Id="VaadinIcons">
                <File Id="VaadinIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.VaadinIcons.dll"></File>
            </Component>
            <Component Id="WeatherIcons">
                <File Id="WeatherIconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.WeatherIcons.dll"></File>
            </Component>
            <Component Id="Zondicons">
                <File Id="ZondiconsDll" Source="$(var.GC Log Config.TargetDir)MahApps.Metro.IconPacks.Zondicons.dll"></File>
            </Component>
            <Component Id="Json">
                <File Id="JsonDll" Source="$(var.GC Log Config.TargetDir)Newtonsoft.Json.dll"></File>
            </Component>
            <Component Id="log4net">
                <File Id="log4netDll" Source="$(var.GC Log Collector.TargetDir)log4net.dll"></File>
            </Component>
            <Component Id="log4netconfig">
                <File Id="log4netCfg" Source="$(var.GC Log Collector.TargetDir)log4net.config"></File>
            </Component>
            <Component Id="RuntimeInformation">
                <File Id="RuntimeInformationDll" Source="$(var.GC Log Collector.TargetDir)System.Runtime.InteropServices.RuntimeInformation.dll"></File>
            </Component>
            <Component Id="Topshelf">
                <File Id="TopshelfDll" Source="$(var.GC Log Collector.TargetDir)Topshelf.dll"></File>
            </Component>
            <Component Id="LiveCharts">
                <File Id="LiveChartsDll" Source="$(var.GC Log Config.TargetDir)LiveCharts.dll"></File>
            </Component>
            <Component Id="LiveChartsWpf">
                <File Id="LiveChartsWpfDll" Source="$(var.GC Log Config.TargetDir)LiveCharts.Wpf.dll"></File>
            </Component>
        </ComponentGroup>

        <DirectoryRef Id="DesktopFolder">
            <Component Id="DesktopShortcut" Guid="54c4cf2a-f3c8-41dc-95a2-79cafa7640b7">
                <Shortcut Id="desktopSC"
                          Name="GC Log Config"
                          Description="GC Log Config"
                          Target="[INSTALLFOLDER]GC Log Config.exe"
                          Icon="appicon.ico">
                </Shortcut>
                <RemoveFolder Id="RemoveDesktopFolder"
                              Directory="DesktopFolder"
                              On="uninstall" />
                <RegistryValue Root="HKCU"
               Key="Software\[Manufacturer]\[ProductName]"
               Name="installed"
               Type="integer"
               Value="1"
               KeyPath="yes" />
            </Component>
        </DirectoryRef>
    </Fragment>

</Wix>

Clean Testing:您应该在干净的虚拟机上试用该包,看看您的 main 上是否有“脏状态”框 - 来自之前的实验。在添加/删除中找到您的包的多个版本并不少见——可能具有不同的名称。这可能以多种方式发生,但通常是因为一个或多个测试版本的主要升级设置配置错误。在卸载所有“克隆”之前,不会卸载文件。也可能有其他原因导致卸载后文件仍然存在。

List Installed Packages: 你可以运行这个脚本来获取你机器上安装的所有MSI包的列表: https://github.com/glytzhkof/all/blob/master/MsiHtmlReport-Mini-V4.vbs

服务安装:使用Windows安装程序时,您不应使用自定义操作来安装服务。这是解释原因的旧答案以及应该如何安装服务的示例:

本质上,您在 MSI 中使用 ServiceInstallServiceControl 结构。