After installing .NET Core 2.1 SDK (great job, BTW), dotnet --info
showed me I had all this installed:
.NET Core SDKs installed:
2.1.4 [C:\Program Files\dotnet\sdk]
2.1.100-preview-007328 [C:\Program Files\dotnet\sdk]
2.1.100-preview-007341 [C:\Program Files\dotnet\sdk]
2.1.100-preview-007354 [C:\Program Files\dotnet\sdk]
2.1.100-preview-007363 [C:\Program Files\dotnet\sdk]
2.1.100-preview-007391 [C:\Program Files\dotnet\sdk]
2.1.100 [C:\Program Files\dotnet\sdk]
2.1.101 [C:\Program Files\dotnet\sdk]
2.1.102 [C:\Program Files\dotnet\sdk]
2.1.103 [C:\Program Files\dotnet\sdk]
2.1.104 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007480 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007509 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007513 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007517 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007570 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007576 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007587 [C:\Program Files\dotnet\sdk]
2.1.200-preview-007589 [C:\Program Files\dotnet\sdk]
2.1.200 [C:\Program Files\dotnet\sdk]
2.1.201 [C:\Program Files\dotnet\sdk]
2.1.300 [C:\Program Files\dotnet\sdk]
How do I remove the old cruft (especially the previews)?
Cough, cough: https://github.com/dotnet/cli/issues/6896. :)
That is related, but yours seems to be mostly around VS automatically uninstalling these, which is interesting, but not my point. When I go to Add/Remove Programs, I can't discern between the previews and the non preview versions (of 2.1.100, for example):
So there doesn't appear to be a way to actually target one of these and uninstall them. It's random which one gets deleted.
@AArnott
When I go to Add/Remove Programs, I can't discern between the previews and the non preview versions (of 2.1.100, for example)
When you click on one of those installed SDKs, it will show you the version. For previews, it should show 4 part version (e.g. 2.1.300.8866 for .Net Core SDK 2.1.300 "RTM"). For non-previews, it will show only 3 parts (e.g. 2.1.300).
Thanks, @svick. I just a few minutes ago figured that out. But it's so tedious to look through each one and uninstall each one (each with its own UAC prompt, uninstall experience, etc).
As a workaround, here's what I came up with:
$products = Get-WmiObject -Class win32_product
$remove = $products |? { $_.name -match 'Microsoft .NET Core SDK - 2.1.200' }
I would then review the contents of $remove
and look to find the one with the highest version number (and assume that's the RTW version I want to keep). Then I would refine the $remove
collection with:
$remove = $products |? { $_.name -match 'Microsoft .NET Core SDK - 2.1.200' -and $_.version -ne '8.50.7609' }
Finally, I would remove all the selected MSIs with:
$remove.identifyingnumber |% { Start-Process msiexec -wait -ArgumentList "/x $_" }
I can't use the /passive
switch because it would no-op since the MSI thinks that a product requires the MSI to be installed. If I remove it, I have two dialogs to click "Yes" to for each MSI, but the process is still faster and less tedious than using the Apps & Features dialog.
Closing this as the question is answered and dotnet/cli#6896 tracks preventing these from accumulating via build-to-build upgrades of VS. If you feel there's a change that is needed to the installer that is not dotnet/cli#6896, file a new issue on the dotnet/cli repo.
Here's a small improvement to reduce errors with @AArnott's excellent script. You can get errors like "This installation package could not be opened" if you aren't in System32 when doing the uninstall.
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Microsoft .NET Core SDK"
}
Write-Host $app.Name
Write-Host $app.IdentifyingNumber
pushd $env:SYSTEMROOT\System32
$app.identifyingnumber |% { Start-Process msiexec -wait -ArgumentList "/x $_" }
popd
Can unnecessary runtimes be removed this way also?
@dub505 I believe those can just be deleted
How do we do this for Mac or Linux?
cc @nguerrera
Hmm, this doesn't work on my pc. I had 12 different .Net Core SDK's installed, when I ran the script, I was prompted xx times to accept uninstalling and everything looked promising. But after the script ended, every of the 12 different SDK's were still there, and i had to remove them manually in Windows App's list. :(
I really look forward to seeing this handled in .NET Core 3.x :)
Thanks for the efforts everyone :)
Which one of them can be safely removed, if I only build from VS 2017/2019?
E.g. does any A.B.(C+n).* supersede A.B.C? A.(B+n).* vs A.B?
Another, faster Powershell script:
$uninstall64 = gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" |
foreach { gp $_.PSPath } | ? { $_ -match "Microsoft .NET Core SDK" } | select DisplayName,UninstallString,PSChildName
$uninstall64.DisplayName | Write-Host
pushd $env:SYSTEMROOT\System32
$uninstall64 |% {
Write-Host $_.DisplayName
$a = "/x " + $_.PSChildName
Start-Process msiexec -wait -ArgumentList $a
}
popd
Instead of msiexec, consider dotnet-sdk-N.N.NNN-win-x64.exe /uninstall
. This appears to perform a more complete uninstallation which also removes them from the Windows Apps & Features list.
The uninstall commands for installed SDKs can be queried from the registry as follows (and the above scripts could be adapted to execute the UninstallString or QuietUninstallString instead of msiexec):
Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where-Object DisplayName -match "Microsoft .NET Core SDK" |
Sort-Object BundleVersion |
Select-Object DisplayName,BundleVersion,UninstallString,QuietUninstallString |
Format-List
And here is a script function that attempts to silently uninstall (except for UAC prompt) outdated SDKs, keeping only the latest patch version of each (unless using the -All param). Dry run with Uninstall-DotNetSdk -WhatIf
or Uninstall-DotNetSdk -WhatIf -All
.
function Uninstall-DotNetSdk {
param (
[parameter(Mandatory = $False)] [switch] $All,
[parameter(Mandatory = $False)] [switch] $WhatIf
)
pushd $env:SystemRoot\System32
Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where-Object DisplayName -match "^Microsoft .NET Core SDK" |
Where-Object BundleVersion -match "^\d+\.\d+\.\d+\d\d\.\d+$" |
Group-Object { ([regex] "^(\d+\.\d+\.\d+)\d\d\.\d+$").Match($_.BundleVersion).Groups[1].Value } |
Sort-Object { [regex]::Replace($_.Name, '\d+', { param($match) $match[0].Value.PadLeft(10,'0') }) } |
ForEach-Object {
$_.Group |
Sort-Object {
$versionMatch = ([regex] "^\d+\.\d+\.\d+(\d\d)\.(\d+)$").Match($_.BundleVersion)
$v1 = $versionMatch.Groups[1].Value
$v2 = $(if ($versionMatch.Groups[2].Value -eq "0") { "9".PadLeft(10,'9') } else { $versionMatch.Groups[2].Value.PadLeft(10,'0') })
"$v1.$v2"
} |
Select-Object -SkipLast $(if ($All) { 0 } else { 1 }) |
ForEach-Object {
if ($_.QuietUninstallString -imatch '^"?([^"]+)"? +(/uninstall.*)$') {
$file = $Matches[1]
$arglist = $Matches[2]
"Uninstall command: `"$file`" $arglist"
if (-not $WhatIf) { Start-Process -FilePath $file -ArgumentList $arglist -Wait }
}
}
}
popd
}
https://github.com/Klocman/Bulk-Crap-Uninstaller works pretty well for this as well
How do we do this for Mac or Linux?
The .NET Core command-line (CLI) tools repository provides uninstall scripts.
Most helpful comment
And here is a script function that attempts to silently uninstall (except for UAC prompt) outdated SDKs, keeping only the latest patch version of each (unless using the -All param). Dry run with
Uninstall-DotNetSdk -WhatIf
orUninstall-DotNetSdk -WhatIf -All
.