In this post we will discuss how we can uninstall an application via Intune. We will focus mainly on the application that were not deployed and installed via Intune, but were installed manually by the end users.
Uninstall application deployed via Intune
First let’s have a quick reminder on how to uninstall an application deployed through Intune from a device. In this example we want to uninstall Wireshark application deployed previous to an endpoint.
Initially we have to create a group that will be used to uninstall the application.
Give a name and description to the group and select the devices on which you want to uninstall the application. Click “Create” to create the group.
Now that the group is ready, move to the application and assign this group to the Uninstall assignment.
As soon the devices communicate with Intune, the application will be uninstalled.
Uninstall application installed by the user
Well, we just described how to uninstall an application that we deployed through Intune. But what happens when a user has installed an application that we don’t want to be installed. To solve this we have to create a script that will perform the uninstallation actions.
First we have to mention that the application installed in an endpoint have relevant registry records in the two below places (take a look at this post for useful paths related to Intune and its operations):
- For 32 bit applications: HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
- For 64 bit applications: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
Our script should check at this locations for the desired app, locate the uninstallation command and execute it. There should be a separate handling between MSI and .exe files, since they are installed and uninstalled differently.
Let’s dive into the script and explore how it functions.
P.S. We are going to work with Wireshark again. The user has installed it in their machine and we want for various reasons (we don’t want to inspect the traffic etc.) to uninstall it.
# There should be a different handling for 32 and 64 bit apps
#First let's search if the app is under the 32 bit path
$32BitPath = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
# Get the application name and the uninstall string
$32BitApp = Get-ChildItem -Path $32BitPath | Get-ItemProperty | Where-Object {($_.DisplayName -match "Wireshark")} | Select-Object -Property DisplayName, UninstallString
if ($32BitApp -ne $null){
$uninstallStringValue = $32BitApp.uninstallstring
# Check if it is .msi or .exe
if ($uninstallStringValue -match "^msiexec*") {
# MSI installer
# Replace the /I with /X and add the quiet parameter
$finalString = $uninstallStringValue + " /quiet /norestart"
$finalString = $finalString -replace "/I", "/X "
$finalString = $finalString -replace "msiexec.exe", ""
Start-Process 'msiexec.exe' -ArgumentList $finalString -NoNewWindow -Wait
}
else {
# Exe installer
# Here we can search if there are specific parameters for the silently uninstallation of the application
# For wireshark the /S start the uninstallation process silently
$finalString = $uninstallStringValue
start-process $finalString -ArgumentList "/S"
}
}
# Next check the 64 bit path
$64BitPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
#Loop Through the apps if name has Adobe and NOT reader
$64BitApp = Get-ChildItem -Path $64BitPath | Get-ItemProperty | Where-Object {($_.DisplayName -match "Wireshark")} | Select-Object -Property DisplayName, UninstallString
if ($64BitApp -ne $null){
$uninstallStringValue = $64BitApp.uninstallstring
# Check if it is .msi or .exe
if ($uninstallStringValue -match "^msiexec*") {
# MSI installer
# Replace the /I with /X and add the quiet parameter
$finalString = $uninstallStringValue + " /quiet /norestart"
$finalString = $finalString -replace "/I", "/X "
$finalString = $finalString -replace "msiexec.exe", ""
Start-Process 'msiexec.exe' -ArgumentList $finalString -NoNewWindow -Wait
}
else {
# Exe installer
# Here we can search if there are specific parameters for the silently uninstallation of the application
# For wireshark the /S start the uninstallation process silently
$finalString = $uninstallStringValue
start-process $finalString -ArgumentList "/S"
}
}
# Check if there is a shortcut in the Start menu and remove it
$startMenuPath = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs"
$appShortcutPath = $startMenuPath + "\Wireshark.lnk"
if ((Test-Path -Path $appShortcutPath) -eq $true){
Remove-Item -Path $appShortcutPath
}
Now that we have the script ready, we have to find a way to deploy it. I prefer to use Remediation scripts for this kind of jobs, in which we will use one detection script that will detect if the application is installed and a remediation script that will uninstall the application.
As you can understand the above script is the remediation script, let’s create the detection script and deploy it to one of our endpoints in order to check the behavior.
$32BitPath = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
# Get the application name and the uninstall string
$32BitApp = Get-ChildItem -Path $32BitPath | Get-ItemProperty | Where-Object {($_.DisplayName -match "Wireshark")} | Select-Object -Property DisplayName, UninstallString
if ($32BitApp -eq $null){
Write-Host "32 bit application does not exist, exit"
# exit 0 to exit
exit 0
}
else{
Write-Host "32 bit application exists, remediate"
# exit 1 to remediate
exit 1
}
$64BitPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
#Loop Through the apps if name has Adobe and NOT reader
$64BitApp = Get-ChildItem -Path $64BitPath | Get-ItemProperty | Where-Object {($_.DisplayName -match "Wireshark")} | Select-Object -Property DisplayName, UninstallString
if ($64BitApp -eq $null){
Write-Host "64 bit application does not exist, exit"
# exit 0 to exit
exit 0
}
else{
Write-Host "64 bit application exists, remediate"
# exit 1 to remediate
exit 1
}
Let’s create the remediation script.
After the creation of the remediation script, it will be deployed to the endpoint and uninstall Wireshark.
Just to mention here that we can further enhance the scripts by using logs for better monitoring. Find how to write and collect logs in the below posts: