Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Installer is not cleaning up package reference tracking provider keys #17723

Open
heaths opened this issue Nov 7, 2023 · 8 comments
Open

Installer is not cleaning up package reference tracking provider keys #17723

heaths opened this issue Nov 7, 2023 · 8 comments
Assignees

Comments

@heaths
Copy link

heaths commented Nov 7, 2023

Various .NET installer packages are not cleaning up the package provider keys in the registry:

image

This can impact installation time and even Windows startup time (at least in older versions; not sure if that's currently the case). A package should clean up it's provider key when uninstalled/upgraded.

For context, I was the creator of the package reference tracking feature first introduced in WiX and implemented later in the Visual Studio Installer. I'm working on some general documentation for how it works and expected behaviors of chainers and packages alike, but for now the main thing is that a package should clean up it's provider key and any dependencies it registers on other packages - the latter of which is crucial to be able to uninstall packages once the non-identity package dependencies are all removed.

@marcpopMSFT
Copy link
Member

@joeloff how expensive is this to fix in our installers? I don't think it's worth cleaning up old entries but new uninstalls it'd be good to have them remove the extra entries.

@heaths
Copy link
Author

heaths commented Nov 7, 2023

Personally, I don't think it's worth cleaning them up. It's possible, but there's certain inherent risk and you'd need a custom action (at least within an MSI) to do it...or dozens if not hundreds of Registry table entries if there's a known quantity.

I should've clarified that this was primarily to mitigate it from continuing in subsequent versions.

Feel free to reach out if you want details on expected behaviors before I get some public docs up, which I'm starting soon. It's an old feature, but I see now was never really documented apart from code in WiX (I was the original author of most of that, but we didn't carry over history from the internal source it seems).

@joeloff
Copy link
Member

joeloff commented Nov 9, 2023

Hi Heath

So the idea is to just run the CA during InstallExecute/InstallFinalize and condition it on Remove=ALL. The CA can read the provider key from the WixDependencyProvider table to generate the key.

Would the long term solution be for the dependency extension to add the CA into the MSI?

We do have a finalizer EXE that runs in the SDK bundle that could potentially do the work - it's already going through the provider keys and can just look for empty .NET ones and clean up the machine.

.NET decided long ago that it wanted to always be SxS, so we never have a stable provider key, exxcept for the .NET host MSI itself which always performs a major upgrade, so its provider keys remains stable across major .NET versions.

The other option would be a RemoveRegistryKey element I think. If we're being uninstalled, at that point there should not be any references left. Both VS and Burn would skip the removal of the MSI if there are remaining dependents. We don't support installing the MSIs for .NET individually.

@heaths
Copy link
Author

heaths commented Nov 9, 2023

To note, Windows Installer is case-sensitive so the property must be REMOVE=ALL.

That said, if you use the WixDependencyExtension and author your provide keys into the MSI, all the right stuff including clean-up should happen automatically. Are you not using the extension currently - not fully, anyway? The MSIs are meant to clean themselves up. If, when you say, the "SDK bundle" is indeed burn, it only writes provider keys for itself and, once again, should clean up after itself.

My understanding of working with your team long, long ago, though, was that builds were upgraded in the M.N.Pxx range, where P increments by 100 such that 8.0.101 upgrades 8.0.100, but 8.0.200 is SxS with 8.0.1xx. Is that not still the case? If so, I highly recommend - to help avoid this problem (probably related) - using a provide key like (prefix made up) DotNet.CLI.8.0.1xx or ...100 or whatever. The idea was to keep tracking dependencies for a package even across upgrades. If dependencies' keys are being left behind and you're ignoring them so that you can install a strict version-specific package e.g., ...8.0.101 over ...8.0.100 that would explain why keys are left behind: they still have subkeys.

@joeloff
Copy link
Member

joeloff commented Nov 9, 2023

We are using the extension, but all our MSIs are SxS, even within an SDK patch. .NET decided to defer the upgrade logic to the bundle or to VS (which acts as the bundle) so it removes the MSI when the old bundle is removed. It never seems to remove the key though. Burn cleans up fine, but the MSIs don't it seems.

While a standalone SDK, e.g. 7.0.101 will upgrade to 7.0.102, it is possible to have both installed if the you installed a standalone SDK (7.0.101), but then installed 7.0.102 as part of VS. .NET stopped shipping the SDK bundles during .NET Core 3.0 (Visual Studio 16.3) and switched to inserting the individual MSIs - the idea was to support targeted fixes that wouldn't require rebuilding all of .NET to just update a single MSI. That has never been leveraged though.

Here's the SDK MSI provider key authoring
https://github.com/dotnet/installer/blob/main/src/redist/targets/packaging/windows/clisdk/provider.wxs

We are not leveraging the Requires element. For installers like the .NET host, the provider key is more stable because it need to be retained across multiple upgrades - it's the only MSI that supports actual major upgrades.

@heaths
Copy link
Author

heaths commented Nov 9, 2023

@mjcavallari-zz it seems there's a discrepancy between what provider VSSetup has and what .NET is using, perhaps. Normally packages' dependencies would clean up just fine. I wonder if dependencies of a provider key are initially there, but then VS removes the package explicitly, and the provider key is left behind.

That said, I thought for sure either Burn or VSSetup would clean up a key all the way to the provider root ("...\Dependencies"). Though, I'm seeing a mix of keys with values and keys without, but none of them in my sampling had anything under "...{ProviderKey}\Dependents".

Was the VSSetup package authoring ever updated with this new SxS approach? At least when I was helping with the original plan and authoring in VS, all the package authoring was done with the assumptions I summarized above.

@joeloff
Copy link
Member

joeloff commented Nov 14, 2023

Burn definitely cleans up. I set up a sandbox, installed .NET 8, then removed it. HKLM\SOFTWARE\Classes\Installer\Dependencies remain, but the provider keys are gone.

@heaths
Copy link
Author

heaths commented Nov 14, 2023

I'll open an internal tracking bug because this may be caused by a difference in the VS package authoring given the changes in the SxS story from when the packages were originally authoring, assuming they weren't updated to follow suit.

/cc @mjcavallari-zz @tydunkel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants