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

How to remove old .NET Core SDKs? #2295

Closed
AArnott opened this issue May 31, 2018 · 17 comments
Closed

How to remove old .NET Core SDKs? #2295

AArnott opened this issue May 31, 2018 · 17 comments

Comments

@AArnott
Copy link
Contributor

AArnott commented May 31, 2018

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)?

@davkean
Copy link
Member

davkean commented May 31, 2018

Cough, cough: https://github.com/dotnet/cli/issues/6896. :)

@AArnott
Copy link
Contributor Author

AArnott commented May 31, 2018

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):
image

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.

@svick
Copy link
Contributor

svick commented May 31, 2018

@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).

@AArnott
Copy link
Contributor Author

AArnott commented May 31, 2018

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.

@nguerrera
Copy link
Contributor

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.

@shanselman
Copy link
Contributor

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

@dub505
Copy link

dub505 commented Sep 26, 2018

Can unnecessary runtimes be removed this way also?

@shanselman
Copy link
Contributor

@dub505 I believe those can just be deleted

@turowicz
Copy link

How do we do this for Mac or Linux?

@turowicz
Copy link

cc @nguerrera

@BrianBergh
Copy link

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 :)

@lostmsu
Copy link

lostmsu commented Apr 4, 2019

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?

@TimKras
Copy link

TimKras commented Apr 6, 2019

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

@penguid
Copy link

penguid commented May 23, 2019

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

@penguid
Copy link

penguid commented May 23, 2019

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
}

@ChrisMcKee
Copy link

https://github.com/Klocman/Bulk-Crap-Uninstaller works pretty well for this as well

@0xced
Copy link

0xced commented Sep 23, 2019

How do we do this for Mac or Linux?

The .NET Core command-line (CLI) tools repository provides uninstall scripts.

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