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

Optional Workload: Finalizer #10356

Merged
merged 20 commits into from
May 5, 2021
Merged

Optional Workload: Finalizer #10356

merged 20 commits into from
May 5, 2021

Conversation

joeloff
Copy link
Member

@joeloff joeloff commented Apr 26, 2021

The finalizer is intended to be run only during uninstall of the standalone SDK. It's intended to remove any optional workload installations that have references to the SDK that's being removed. In short, it enumerates all the MSI dependency provider keys for the dependent value associated with the SDK.

If there are more than one dependent, it simply removes the SDK's reference. Otherwise, if the SDK is the only dependent, it removes the reference and then uninstalls the MSI, provided the MSI is still installed as sometimes, there can be corrupted/orphaned providers.

Below is an example of how the finalizer would be chained into the SDK bundle. The finalizer will only execute during uninstalls and because we don't actually install anything, the EXE's detection state is based on the fact that the bundle is being removed (BOOTSTRAPPER_ACTION_UNINSTALL >= 3). The install condition is set to true when the bundle is being installed, repaired or modified (BOOTSTRAPPER_ACTION_INSTALL >= 4). If the InstallCondition is false at install time, the bundle will remove the EXE package (see this). The SDK_DEP property will be set based on the dependent value associated with the SDK.

      <ExePackage SourceFile="$(var.WorkloadFinalizer.TargetPath)"
                  DetectCondition="WixBundleAction >= 3"
                  UninstallCommand="&quot;[WixBundleLog_WorkloadFinalizer.exe]&quot; [SDK_DEP]"
                  Vital="no"
                  InstallCondition="(WixBundleAction >= 4)">
      </ExePackage>

The finalizer is using the WiX SDK (dutil.lib). It is however not using deputil. While deputil does provide functionality around dependency providers, it is intended to handle a specific provider key whereas the finalizer needs to process all provider keys.

@joeloff joeloff changed the title Optional Workload: Finalizer [WIP] Optional Workload: Finalizer Apr 26, 2021
ReleaseStr(sczProductId);
ReleaseStr(sczProviderKey);
ReleaseStr(sczDependentsKey);
ReleaseRegKey(hkDependentsKey);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know regutil (and I can't find it around here), but I would assume that releasing something twice is not nice...
Also - we may call release with null... not sure if that works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regutil is coming from the WiX SDK, defined as #define ReleaseRegKey(h) if (h) { ::RegCloseKey(h); h = NULL; }
strutil (also WiX SDK), is defined as #define ReleaseStr(pwz) if (pwz) { StrFree(pwz); }, though it doesn't make the pointer NULL.

I was concerned about too many open handles since we could be enumerating thousands of keys/subkeys, but if we hit an error we'd fall into the exit block with an unknown state of the various handles.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - so it's macro magic... 😢 ... sometime I hate what people do with C++.

Anyway - in that case you're right - it will work.

Copy link
Member

@dsplaisted dsplaisted left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been forever since I've done C++ and I'm not really familiar with the registry and MSI APIs, but generally looks good.

@joeloff
Copy link
Member Author

joeloff commented Apr 29, 2021

I've pushed some of the infrastructure changes needed to build the finalizer and add it to the SDK install bundle.

@joeloff
Copy link
Member Author

joeloff commented May 2, 2021

This can be written in few lines of C# using Microsoft.Deployment.WindowsInstaller(.Linq) from WiX (which is already required by your solution) without adding so much infrastructure to build native projects. That is much easier to write, debug and maintain.

Indeed it can, except that if it's managed code, we can't guarantee that .NET Framework is installed, and a self contained .NET Core application adds around 20-30MB to the installer size based on a number of early prototypes. This should not have too much maintenance and should be a one-off cost (which is also the reason for using the WiX SDK that has good wrappers for some of the registery functions)

@joeloff joeloff changed the title [WIP] Optional Workload: Finalizer Optional Workload: Finalizer May 4, 2021
@joeloff joeloff merged commit 3c87114 into dotnet:main May 5, 2021
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

Successfully merging this pull request may close these issues.

3 participants