Ensure finalizer doesn't remove workloads during upgrades (#10999)
This commit is contained in:
parent
addb1b1961
commit
ef74b6ca71
3 changed files with 290 additions and 161 deletions
|
@ -8,10 +8,11 @@ extern "C" HRESULT Initialize(int argc, wchar_t* argv[])
|
|||
HRESULT hr = S_OK;
|
||||
|
||||
// We're not going to do any clever parsing. This is intended to be called from
|
||||
// the standalone bundle only and there will only be two parameters:
|
||||
// the standalone bundle only and there will only be a fixed set of parameters:
|
||||
// 1. The path of the log file, created by the bundle.
|
||||
// 2. The dependent we're trying to clean up.
|
||||
if (argc != 3)
|
||||
// 2. The full SDK version, e.g. 6.0.105 or 6.0.398-preview19
|
||||
// 3. Target platform to search under the registry key to locate installed SDKs.
|
||||
if (4 != argc)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_INVALID_COMMAND_LINE);
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ LExit:
|
|||
return hr;
|
||||
}
|
||||
|
||||
extern "C" HRESULT RemoveDependent(LPWSTR sczDependent, BOOL* pbRestartRequired)
|
||||
extern "C" HRESULT RemoveDependent(LPWSTR sczDependent, BOOL * pbRestartRequired)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HKEY hkInstallerDependenciesKey = NULL;
|
||||
|
@ -184,17 +185,145 @@ LExit:
|
|||
return hr;
|
||||
}
|
||||
|
||||
extern "C" HRESULT ParseSdkVersion(LPWSTR sczSdkVersion, INT * piMajor, INT * piMinor, INT * piFeatureBand)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT cVersionParts = 0;
|
||||
LPWSTR* rgsczVersionParts = NULL;
|
||||
int iPatch = 0;
|
||||
|
||||
hr = StrSplitAllocArray(&rgsczVersionParts, &cVersionParts, sczSdkVersion, L".");
|
||||
ExitOnFailure(hr, "Failed to split version.");
|
||||
|
||||
// We only care about the major.minor.patch values
|
||||
// to convert to a feature band. If we don't have at least
|
||||
// all 3 parts, we'll ignore the value.
|
||||
if (3 > cVersionParts)
|
||||
{
|
||||
ExitOnFailure(E_INVALIDARG, "Invalid SDK version: %ls %li", sczSdkVersion, cVersionParts);
|
||||
}
|
||||
|
||||
hr = StrStringToInt32(rgsczVersionParts[0], 0, piMajor);
|
||||
ExitOnFailure(hr, "Invalid major version.");
|
||||
hr = StrStringToInt32(rgsczVersionParts[1], 0, piMinor);
|
||||
ExitOnFailure(hr, "Invalid minor version.");
|
||||
|
||||
// If this is a valid SDK version the 'patch' should be a 3 digit field
|
||||
// containing the feature band and patch level, e.g. 100 or 207. We
|
||||
// can discard any prerelease labels from the semantic version.
|
||||
hr = StrStringToInt32(rgsczVersionParts[2], 3, &iPatch);
|
||||
ExitOnFailure(hr, "Invalid patch version.");
|
||||
|
||||
if (100 > iPatch)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
ExitOnFailure(hr, "Invalid SDK feature band and patch level.");
|
||||
}
|
||||
|
||||
*piFeatureBand = iPatch - (iPatch % 100);
|
||||
|
||||
LExit:
|
||||
ReleaseStrArray(rgsczVersionParts, cVersionParts);
|
||||
return hr;
|
||||
}
|
||||
|
||||
extern "C" HRESULT DetectSdk(LPWSTR sczSdkFeatureBandVersion, LPWSTR sczArchitecture, BOOL * pbInstalled)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HKEY hkInstalledSdkVersionsKey = NULL;
|
||||
LPWSTR sczInstalledSdkVersionsKeyName = NULL;
|
||||
LPWSTR sczSdkVersion = NULL;
|
||||
DWORD dwSdkVersionValueType = 0;
|
||||
int iInstalledMajor = 0;
|
||||
int iInstalledMinor = 0;
|
||||
int iInstalledFeatureBand = 0;
|
||||
int iExpectedMajor = 0;
|
||||
int iExpectedMinor = 0;
|
||||
int iExpectedFeatureBand = 0;
|
||||
|
||||
hr = ParseSdkVersion(sczSdkFeatureBandVersion, &iExpectedMajor, &iExpectedMinor, &iExpectedFeatureBand);
|
||||
|
||||
LogStringLine(REPORT_STANDARD, "Detecting installed SDK versions for %ls", sczSdkFeatureBandVersion);
|
||||
|
||||
// Scan the registry to see if any SDK matching the feature band we're trying to
|
||||
// clean up is still installed. All the installation keys reside in the 32-bit hive.
|
||||
hr = StrAllocConcatFormatted(&sczInstalledSdkVersionsKeyName, L"SOFTWARE\\WOW6432Node\\dotnet\\Setup\\InstalledVersions\\%ls\\sdk", sczArchitecture);
|
||||
ExitOnFailure(hr, "Failed to allocate string for installed SDK versions.");
|
||||
|
||||
LogStringLine(REPORT_STANDARD, "Scanning %ls", sczInstalledSdkVersionsKeyName);
|
||||
|
||||
hr = RegOpen(HKEY_LOCAL_MACHINE, sczInstalledSdkVersionsKeyName, KEY_READ, &hkInstalledSdkVersionsKey);
|
||||
ExitOnFailure(hr, "Failed to read installed versions key.");
|
||||
|
||||
for (DWORD dwSdkVersionsValueIndex = 0;; ++dwSdkVersionsValueIndex)
|
||||
{
|
||||
hr = RegValueEnum(hkInstalledSdkVersionsKey, dwSdkVersionsValueIndex, &sczSdkVersion, &dwSdkVersionValueType);
|
||||
|
||||
if (E_NOMOREITEMS == hr)
|
||||
{
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
ExitOnFailure(hr, "Failed to read SDK version values from registry.");
|
||||
|
||||
hr = ParseSdkVersion(sczSdkVersion, &iInstalledMajor, &iInstalledMinor, &iInstalledFeatureBand);
|
||||
ExitOnFailure(hr, "Failed to parse %ls", sczSdkVersion);
|
||||
|
||||
LogStringLine(REPORT_STANDARD, "SDK version detected: %ls, mapping to %li.%li.%li.", sczSdkVersion, iInstalledMajor, iInstalledMinor, iInstalledFeatureBand);
|
||||
|
||||
// Bail out on the first match.
|
||||
if ((iInstalledMajor == iExpectedMajor) && (iInstalledMinor == iExpectedMinor) && (iInstalledFeatureBand == iExpectedFeatureBand))
|
||||
{
|
||||
*pbInstalled = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
ReleaseRegKey(hkInstalledSdkVersionsKey);
|
||||
ReleaseStr(sczInstalledSdkVersionsKeyName);
|
||||
ReleaseStr(sczSdkVersion);
|
||||
return hr;
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD dwExitCode = 0;
|
||||
LPWSTR sczDependent = NULL;
|
||||
LPWSTR sczFeatureBandVersion = NULL;
|
||||
BOOL bRestartRequired = FALSE;
|
||||
BOOL bSdkFeatureBandInstalled = FALSE;
|
||||
int iMajor = 0;
|
||||
int iMinor = 0;
|
||||
int iFeatureBand = 0;
|
||||
|
||||
hr = ::Initialize(argc, argv);
|
||||
ExitOnFailure(hr, "Failed to initialize.");
|
||||
|
||||
sczDependent = argv[2];
|
||||
// Convert the full SDK version to a feature band version
|
||||
hr = ParseSdkVersion(argv[2], &iMajor, &iMinor, &iFeatureBand);
|
||||
ExitOnFailure(hr, "Failed to parse version, %ls.", argv[2]);
|
||||
|
||||
hr = StrAllocConcatFormatted(&sczFeatureBandVersion, L"%li.%li.%li", iMajor, iMinor, iFeatureBand);
|
||||
ExitOnFailure(hr, "Failed to create feature band version.");
|
||||
|
||||
// Create the dependent value, e.g., Microsoft.NET.Sdk,6.0.300,arm64
|
||||
hr = StrAllocConcatFormatted(&sczDependent, L"Microsoft.NET.Sdk,%ls,%ls", sczFeatureBandVersion, argv[3]);
|
||||
ExitOnFailure(hr, "Failed to create dependent.");
|
||||
LogStringLine(REPORT_STANDARD, "Setting target dependent to %ls.", sczDependent);
|
||||
|
||||
hr = ::DetectSdk(sczFeatureBandVersion, argv[3], &bSdkFeatureBandInstalled);
|
||||
ExitOnFailure(hr, "Failed to detect installed SDKs.");
|
||||
|
||||
if (bSdkFeatureBandInstalled)
|
||||
{
|
||||
goto LExit;
|
||||
}
|
||||
|
||||
LogStringLine(REPORT_STANDARD, "SDK with feature band %ls could not be found.", sczFeatureBandVersion);
|
||||
|
||||
hr = ::RemoveDependent(sczDependent, &bRestartRequired);
|
||||
ExitOnFailure(hr, "Failed to remove dependent \"%ls\".", sczDependent);
|
||||
|
||||
|
@ -204,6 +333,8 @@ int wmain(int argc, wchar_t* argv[])
|
|||
}
|
||||
|
||||
LExit:
|
||||
ReleaseStr(sczDependent);
|
||||
ReleaseStr(sczFeatureBandVersion);
|
||||
LogUninitialize(TRUE);
|
||||
RegUninitialize();
|
||||
WiuUninitialize();
|
||||
|
|
|
@ -206,7 +206,7 @@
|
|||
DetectCondition="WixBundleAction >= 3"
|
||||
Id="Finalizer"
|
||||
InstallCondition="WixBundleAction >= 4"
|
||||
UninstallCommand=""[WixBundleLog_Finalizer]" $(var.SdkDependent)"
|
||||
UninstallCommand=""[WixBundleLog_Finalizer]" $(var.NugetVersion) $(var.Platform)"
|
||||
Vital="no" />
|
||||
</Chain>
|
||||
</Bundle>
|
||||
|
|
|
@ -45,6 +45,4 @@
|
|||
|
||||
<?define DependencyKey = "$(var.DependencyKeyName)_$(var.SDKBundleVersion)_$(var.Platform)"?>
|
||||
<?define DependencyKeyId = "$(var.DependencyKey)" ?>
|
||||
<!-- The dependent value associated with this SDK when creating reference counts for optional workloads. -->
|
||||
<?define SdkDependent = "Microsoft.NET.SDK,$(var.NugetVersion),$(var.Platform)"?>
|
||||
</Include>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue