This article covers why an uninstall Worklet reports a timeout, fails to detect an installed application, or runs without removing anything, and how to correct each case.
Symptoms
- COMMAND TIMED OUT appears in the Activity Log.
- The application is not detected as installed, so remediation never runs.
- The Worklet reports success but the application is still present.
1. The uninstall command is not actually silent
This is the most common cause of a timeout. If the uninstaller displays any prompt, nothing is there to answer it, the process waits indefinitely, and the command is eventually killed and reported as timed out.
The trap is the UninstallString value in the registry. For applications installed by Windows Installer it usually looks like this:
MsiExec.exe /I{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}That is /I, which is install and repair mode, not uninstall. Running it opens an interactive dialog. To uninstall silently you need /X with silent switches:
msiexec.exe /x {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} /qn /norestartTwo further points:
- Many registry entries also provide
QuietUninstallString, which is the vendor's own silent uninstall command. Use it when it exists rather than constructing one. -
/Sis not a universal silent switch. It applies to NSIS installers. Inno Setup uses/VERYSILENT, Windows Installer uses/qn, and others differ again. Applying/Sto an installer that does not recognize it produces exactly the interactive prompt you were trying to avoid.
2. COMMAND TIMED OUT does not always mean a timeout
This error is reported in two different situations:
- The script genuinely exceeded the execution window on that device.
- The script completed but returned a non-zero exit code. Because of how PowerShell is launched for Worklets, an
exit 1frequently surfaces as Exit Code 124, COMMAND TIMED OUT.
Check whether the Activity Log entry contains script output. If your script printed its progress and then reported a timeout, it ran to completion and the exit code is what you are looking at. Using a different non-zero value such as exit 2 in evaluation code keeps genuine timeouts distinguishable.
3. The application name does not match
Confirm the name against Settings > Apps > Installed apps, or read it from the registry directly, which is what the Worklet does.
When using -like, the value needs wildcards. A bare name matches only an exact string, and an empty value matches nothing at all:
$appName = '*Application Name*'
Vendors frequently include version numbers, editions, or architecture in the display name, so a wildcard match on a distinctive fragment is more reliable than the full name.
4. Execution context
Worklets run PowerShell in 32-bit mode as the SYSTEM account. On 64-bit Windows a 32-bit process reading HKLM\SOFTWARE is redirected into WOW6432Node, so enumerating both paths explicitly, as the examples below do, matters. Test scripts under the same conditions before concluding the uninstall logic is wrong. See How to Test a PowerShell Script Locally for Worklets.
Example code
Evaluation Code
$appName = '*Application Name*'
$uninstReg = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
$installed = @(Get-ItemProperty -Path $uninstReg -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like $appName })
if ($installed) {
Write-Output "Found $($installed.Count) matching installation(s). Remediation required."
exit 2
} else {
Write-Output "Application not present."
exit 0
}Remediation Code
$appName = '*Application Name*'
$uninstReg = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
$installed = @(Get-ItemProperty -Path $uninstReg -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like $appName })
foreach ($app in $installed) {
Write-Output "Processing: $($app.DisplayName)"
if ($app.QuietUninstallString) {
Write-Output "Using QuietUninstallString."
Start-Process -FilePath "cmd.exe" -ArgumentList "/c", $app.QuietUninstallString -Wait -NoNewWindow
}
elseif ($app.UninstallString -match '\{[0-9A-Fa-f\-]{36}\}') {
$productCode = $Matches[0]
Write-Output "Uninstalling Windows Installer product $productCode"
Start-Process -FilePath "msiexec.exe" -ArgumentList "/x", $productCode, "/qn", "/norestart" -Wait -NoNewWindow
}
else {
Write-Output "Non-MSI uninstaller found. Confirm the correct silent switch for this vendor before automating:"
Write-Output $app.UninstallString
}
}Set $appName in both scripts to the same value. The evaluation reports the device compliant once no matching entry remains.
Do not use Win32_Product to find or remove applications
A common alternative is to query the Win32_Product WMI class and call its Uninstall method. Avoid this. Querying that class makes Windows Installer enumerate every installed package and run a consistency check against each one, which is slow, writes reconfiguration entries into the event log, and can repair or reinstall applications as a side effect. On uninstall Worklets it is a recurring contributor to timeouts. The registry method above is faster and does not modify anything while reading.
Applications that cannot be removed this way
Some products do not support a standard silent uninstall and require the vendor's own removal tool or a documented procedure. Veritas NetBackup Client is one example. If the vendor publishes a specific uninstall method, use it rather than the registry uninstall string.
You can also check whether Automox considers an application removable using the is_uninstallable field returned by the GetDevicePackages API call. See the Automox API documentation.
A note on scope
Automox Support can help you interpret Worklet execution behavior, exit codes, and Activity Log output. Writing and maintaining custom uninstall scripts is outside that scope, and the Automox Professional Services team can assist if you would like help building one.