Managing Installations with PowerShell and InTune
Managing software installations across a large organization can be a challenging task. Problems can arise when system-wide installations conflict with per-user installations, especially if end-users don’t have administrative privileges. In this blog post, we’ll cover a PowerShell script that can help you uninstall any software application from both the system level and the user level. We’ll also discuss how to deploy this script via InTune for automated execution across multiple devices.
The Problem
When software is installed system-wide, users without administrative rights find it difficult to update or uninstall it. Even if you direct them to install a per-user version of the same software, shortcuts and application references might still point to the system-wide version, creating conflicts.
The Solution
The script performs several key actions:
- It searches for the target software at both system-wide and user-specific levels.
- Uninstalls all found versions of the software.
- Logs all actions to a text file for auditing.
Here is a generic version of the script, which you can adapt to fit your specific needs.
# Ensure the target logging directory exists
$directory = "C:\tmp"
if (-not (Test-Path $directory)) {
New-Item -ItemType Directory -Path $directory -Force
}
$outputFile = "C:\tmp\Uninstall-Software.txt"
# Target software name
$softwareName = "TargetSoftware" # Replace this with the name of the software you want to uninstall
$uninstallPaths = @{
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall' = 'System-wide'
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' = 'System-wide'
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall' = 'User-specific'
}
$softwareKeys = @()
foreach ($path in $uninstallPaths.Keys) {
$softwareKeys += Get-ChildItem -Path $path | Where-Object { (Get-ItemProperty -Path $_.PsPath).DisplayName -like "*$softwareName*" } | ForEach-Object {
[PSCustomObject]@{
Key = $_.PsPath
DisplayName = (Get-ItemProperty -Path $_.PsPath).DisplayName
Version = (Get-ItemProperty -Path $_.PsPath).DisplayVersion
InstallScope = $uninstallPaths[$path]
UninstallString = (Get-ItemProperty -Path $_.PsPath).UninstallString
}
}
}
function WriteLog {
param (
[Parameter(Mandatory=$true)]
[string]$message
)
# Format current date and time
$currentDateTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
# Prefix message with current date and time
$logMessage = "[$currentDateTime] $message"
Write-Output $logMessage
Add-Content -Path $outputFile -Value $logMessage
}
foreach ($software in $softwareKeys) {
$message = "Uninstalling $($software.DisplayName) (Version: $($software.Version)) [Install Scope: $($software.InstallScope)]..."
WriteLog $message
if ($software.UninstallString) {
# Execute the uninstall command
Start-Process -Wait -FilePath "cmd.exe" -ArgumentList "/c $($software.UninstallString) /quiet /norestart"
$completedMessage = "$($software.DisplayName) (Version: $($software.Version)) has been uninstalled."
WriteLog $completedMessage
}
}
if (-not $softwareKeys) {
$noSoftwareMessage = "No $softwareName versions found."
WriteLog $noSoftwareMessage
}
How the Script Works
-
Log Directory: The script first ensures that a directory for logs exists, creating one if it doesn’t.
-
Registry Scanning: The script then looks into specific registry paths where installed software details are usually kept, both for 32-bit and 64-bit installations.
-
Software Search: It identifies any software with a specific keyword in its display name from the registry entries.
-
Uninstallation: For each version found, it uses the
UninstallString
from the registry to execute a silent uninstallation. -
Logging: Finally, it logs all actions taken during the process to a text file, which can be audited later if needed.
Deploying Through InTune
-
Package the Script: Use the IntuneWinAppUtil.exe utility to package your PowerShell script into an
.intunewin
file. -
InTune Upload: Go to the Microsoft Endpoint Manager admin center, navigate to
Apps > All apps > Add
, and upload your.intunewin
package. -
Configuration: During the upload, set the install and uninstall commands. Use something like
powershell -executionpolicy bypass -file YourScriptName.ps1
as the install command. -
User Assignment: Finally, assign the ‘app’ to the relevant user groups in your organization.
Managing software installations in a large organization need not be a daunting task. With the right PowerShell script and InTune, you can efficiently handle software conflicts and ensure that users are running the most up-to-date versions of all necessary applications. This approach reduces the need for administrative intervention and ensures a smoother user experience across your organization.