Need to remove .NET runtimes from Intune-managed devices? This guide shows how to automate the detection and removal of .NET 6—or any .NET runtime—using PowerShell and Intune Proactive Remediations.
Overview
Old .NET runtimes can remain on endpoints even after upgrades, creating security and compliance risks. Manual removal is not scalable. This post explains how to automate .NET runtime detection and removal across your environment using Intune and PowerShell.
Note: While the scripts target .NET 6 by default, you can easily adapt them to remove any .NET runtime by updating the package names.
Why Remove Old .NET Runtimes?
- Security: Unpatched runtimes are a vulnerability risk.
- Compliance: Legacy software can trigger audit findings.
- Clarity: Clean inventory and reporting.
Solution: Automated .NET Runtime Cleanup
PowerShell scripts deployed via Intune Proactive Remediations can detect and uninstall .NET runtimes silently, at scale, and without user interaction.
Key Features
- Adaptable: Update package names to target any .NET runtime version.
- SYSTEM Context Support: Works reliably when run by Intune.
Ensuring Winget Works in SYSTEM Context
A common issue is winget not being available in the SYSTEM PATH when scripts run via Intune. The solution includes a PowerShell function to locate winget and add its path to the session, ensuring it works every time.
This method is based on research from ScriptingHouse.
function Add-WinGetToPath {
$WinGetPaths = @(
"$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe",
"$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe",
"$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe"
)
$WinGetPath = $null
foreach ($path in $WinGetPaths) {
$foundPath = Get-ChildItem $path -ErrorAction SilentlyContinue | Select-Object -First 1
if ($foundPath) {
$WinGetPath = $foundPath.DirectoryName
break
}
}
if ($WinGetPath -and -not (($env:PATH -split ';') -contains $WinGetPath)) {
$env:PATH += ";$WinGetPath"
Write-Output "Added winget path ($WinGetPath) to current session"
}
}
Script Details
Detection Script: Uses winget list to find installed .NET runtimes. Exits with code 1 if found (triggers remediation), or 0 if not. Ensures winget is available before running.
Remediation Script: Uninstalls all targeted .NET runtime packages using winget uninstall --all-versions --silent. Handles missing packages and logs actions.
Default Targeted Packages:
- Microsoft.DotNet.Runtime.6
- Microsoft.DotNet.AspNetCore.6
- Microsoft.DotNet.DesktopRuntime.6
To remove other .NET runtimes, update the package names in the scripts. Full scripts are available on GitHub.
Implementation Guide
- Download: Get
Detection.ps1andRemediation.ps1from GitHub. - Create Remediation: In Intune (Endpoint Manager → Reports → Endpoint analytics → Proactive remediations), create a new remediation.
- Configure: Upload scripts, set to run as System, and enable 64-bit PowerShell.
- Assign & Test: Assign to a test group first. Monitor results in Intune.
- Deploy: Roll out to production after successful testing.
Lessons Learned
- Winget in SYSTEM: Requires explicit path handling for reliability.
- Error Handling: Robust logging and error management are essential.
- Adaptability: Scripts can be reused for other .NET versions with minor edits.
Credits
Special thanks to ScriptingHouse for their solution to the winget SYSTEM context issue.
Ready to automate .NET runtime removal?
Get the scripts from GitHub and adapt them for your environment.

