Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wix toolset: complete cleanup after "disallowing uninstallation of component since another client exists"

today I found out that my installer does not uninstall correctly anymore. Meaning my app is not shown in control panel anymore after uninstalling from there but all files are still present. I looked at the log files and I see a lot of "disallowing uninstallation of component since another client exists" which afaik means I screwed up..

So what is the best way to cleanup my pc and to prevent it from happening in the future? What could have caused this? afaik a not completely uninstalled previous version of my app is the reason for this error?

Unfortunately, using VM is not possible for various reasons..

FYI: For developing and test purposes I usually test and create installer with 1.0.xxxxx where xxxxx often stays the same. My upgradecode is always the same. In addition I am using heat and wherever possible I am letting wix auto-generate GUIDs. Furthermore I have one CA to show my readme file after installation and one to execute a batch file (modifies registry entries using powercfg). Upon uninstall a executable is run to import an .reg file to restore modified registry entries (because they would be uninstalled by wix).

like image 886
sceiler Avatar asked Nov 04 '14 15:11

sceiler


2 Answers

We recently had the case that one of our development machines couldn't remove all components on uninstallation. On other machines, however, the WiX setup worked as intended.

So, if you uninstalled incorrectly an earlier version of your product and getting the message Disallowing uninstallation of component: {GUID} since another client exists there is a high chance that you have orphan components lying around in your registry.

There is a much more elegant solution for deleting those hidden registry keys with PowerShell instead of using, as mentioned by others, a 3rd party application.

$productName = "Path\\YourProductName"  # this should basically match against your previous
# installation path. Make sure that you don't mess with other components used 
# by any other MSI package

$components = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\
$count = 0

foreach ($c in $components) 
{
    foreach($p in $c.Property)
    {
        $propValue = (Get-ItemProperty "Registry::$($c.Name)" -Name "$($p)")."$($p)"
        if ($propValue -match $productName) 
        {
            Write-Output $propValue
            $count++
            Remove-Item "Registry::$($c.Name)" -Recurse
        }
    }
}

Write-Host "$($count) key(s) removed"

If you want to get a more detailed explanation about the cause of the message disallowing uninstallation... take a look here.

like image 133
Yannic Hamann Avatar answered Sep 17 '22 03:09

Yannic Hamann


It sounds like you need to uninstall the features (or whole products) that have installed your unwanted components. Windows Installer has an API for querying components, features and products. The WiX Toolset has incorporated a wrapper around the API called DTF. You can use it to query features by component.

So, break out your favorite .NET script runner (mine is LINQPad) and run a query. For example, to find out how to remove "candle.exe":

// using System.Linq;
// using Microsoft.Deployment.WindowsInstaller;

// <ref>"C:\Program Files (x86)\WiX Toolset v3.8\SDK\
         Microsoft.Deployment.WindowsInstaller.dll"</ref>

ComponentInstallation.AllComponents
    .Where(c=>c.State == InstallState.Local)
    .Where(c => c.Path.ToLowerInvariant().EndsWith(@"\candle.exe"))
    .SelectMany(c => c.ClientProducts
        .SelectMany(p => p.Features.Where(f => f.Usage.UseCount > 0)
            .Select(f => new {
                c.Path, 
                f.FeatureName,
                p.LocalPackage,
                p.UserSid, 
                p.ProductCode})))

LINQPad Instant Share

LINQPad Output

Then, run msiexec /x <ProductCode> to remove all the features of the products

or msiexec /i <LocalPackage> REMOVE=<FeatureName> to remove just the features that installed the component.

like image 38
Tom Blodget Avatar answered Sep 17 '22 03:09

Tom Blodget