Simon Taisbak
Simon Taisbak

Reputation: 129

How to uninstall .NET SDK previews and older versions when uninstall tool doesn't recognise them

I'd like to uninstall .NET 5 and .NET 6 previews - and just keep the latest .NET 6.

However, the uninstall utility only let me uninstall the version I'd like to keep.

Neither are the old versions present for removal in Settings/Apps & features (Windows 10).

All SDKs have been installed using proper install utility - no zip files - or by Visual Studio.

I have uninstalled Visual Studio - I use VSCode instead.

List of the current SDKs:

C:\>dotnet --list-sdks

5.0.400 [C:\Program Files\dotnet\sdk]
6.0.100-preview.7.21379.14 [C:\Program Files\dotnet\sdk]
6.0.101 [C:\Program Files\dotnet\sdk]

List of uninstallable SDKs (using the uninstall utility):

C:\Program Files (x86)\dotnet-core-uninstall>dotnet-core-uninstall list

.NET Core SDKs:
  6.0.101  x64    [Used by Visual Studio. Specify individually or use --force to remove]

.NET Core Runtimes:

ASP.NET Core Runtimes:

.NET Core Runtime & Hosting Bundles:

C:\Program Files (x86)\dotnet-core-uninstall>dotnet-core-uninstall --version
1.5.255402+e07a3c995ec2d3cf449d37eb50c87e180da12544

Any hints on how to get rid of them is greatly appreciated.

Upvotes: 12

Views: 23406

Answers (3)

XperiAndri
XperiAndri

Reputation: 1208

Use this script if dotnet-core-uninstall does not help

# Path to the installer folder
$InstallerFolder = Resolve-Path "C:\Windows\Installer"

# Search for all .msi files in the current folder
$MsiFiles = Get-ChildItem -Path $InstallerFolder -Filter *.msi

# Get the ShellFolder once
$Shell = New-Object -COMObject Shell.Application
$ShellFolder = $Shell.NameSpace($InstallerFolder.Path)

# Loop through each .msi file
foreach ($File in $MsiFiles) {
    $ShellFile = $ShellFolder.ParseName($File.Name)

    # Get the subject of the .msi file
    $Subject = $ShellFile.ExtendedProperty("System.Subject")

    # Check if the subject contains either specified string format
    if ($Subject -like "*9.0.100-rc.2*" -or $Subject -like "*9.0.0 RC 2*") {
        # Execute uninstallation and wait for it to complete
        Write-Host "Uninstalling $File"
        $process = Start-Process msiexec.exe -ArgumentList "/x $($File.FullName) /norestart" -Wait
        Write-Host "Uninstalled $File"
    }
}

Upvotes: 0

Max
Max

Reputation: 7090

I found a GitHub Issue from which I have made a Gist which lists all installed software, including any that is not visible.

Examples

Get ALL software containing (case-SENSITIVE) .NET
Get-Installed -Name .NET

Get ALL software containing (case-SENSITIVE) .NET AND 3.1.10
Get-Installed -Name .NET | Where-Object {$_.DisplayName.Contains("3.1.10")}

Get ALL software containing (case-SENSITIVE) .NET AND 3.1.10 AND Remove that software
Get-Installed -Name .NET | Where-Object {$_.DisplayName.Contains("3.1.10")} | Select -Expand PsChildName | Remove-Installed

function Get-Installed {
    [CmdletBinding()]
    param (
        # The name of the software
        [Parameter(Mandatory = $true)]
        [string] $Name
    )
    
    begin {
        $PATHS = @(
            "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
            "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
        )

    }
    
    process {
        $installed = $null
        ForEach ($path in $PATHS) {
            $installed += Get-ChildItem -Path $path |
            ForEach-Object { Get-ItemProperty $_.PSPath } |
            Where-Object { $null -ne $_.DisplayName -and $_.DisplayName.Contains($Name) } |
            Select-Object DisplayName, DisplayVersion, PSChildName |
            Sort-Object -Property DisplayName
        }
        $installed
    }
    
    end {
        
    }
}

function Remove-Installed {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Guid
    )
    
    process {
        Write-Verbose "Removing $Guid"
        $a = "/x " + $Guid
        Start-Process msiexec -Wait -ArgumentList $a
    }
    
}

# Examples
#
# Get ALL software containing (case-SENSITIVE) .NET
# Get-Installed -Name .NET  
# 
# Get ALL software containing (case-SENSITIVE) .NET AND 3.1.10
# Get-Installed -Name .NET | Where-Object {$_.DisplayName.Contains("3.1.10")} 
#
# Get ALL software containing (case-SENSITIVE) .NET AND 3.1.10 AND Remove those software
# Get-Installed -Name .NET | Where-Object {$_.DisplayName.Contains("3.1.10")} | Select -Expand PsChildName | Remove-Installed
# 

Upvotes: 7

Marco
Marco

Reputation: 391

I know this is a few months late, but this ended up being quite high up on Google, so just adding the answer here.

You can use the dotnet-core-uninstall tool, https://learn.microsoft.com/en-us/dotnet/core/additional-tools/uninstall-tool?tabs=windows

And can run: dotnet-core-uninstall remove --all-previews-but-latest If you just want to remove the preview/keep .Net 5, your question was just to keep .Net 6, so you can use --all-below 6.0.101 --sdk

You can do a dry run by adding it to the command (dry-run and whatif are synonyms, you can use either): dotnet-core-uninstall whatif --all-below 6.0.101 --sdk

Upvotes: 10

Related Questions