PS Script to uninstall GUID via GPO Hangs on user device

I’m having several issues trying to force uninstall applications by GUID that bypasses UAC and skips the “Are you sure you want to uninstall” prompts. I’m newer to this so I’m trying to figure this out on my own but no luck.

GPO configured to have a PowerShell script for Computer Configuration > Windows Settings > Scripts for Startup pointing to network share location of script.
Computer Config > Administrative Template > Windows Components > Windows Powershell “Turn on Script Execution” enabled to allow all scripts.

When pushed out the user device hangs and doesn’t uninstall anything. Is there a GPO setting I’m missing or is my script completely wrong? Or maybe there is a better method of doing this through GPO?

$msiGUIDs = @(
	"{3C957E7F-B142-4815-9AC1-484FD15F36A9}",
	"{36559883-c400-43f5-8c9e-0853f441b301}",
	"{9487E0E2-95E9-4B9C-802E-BB6CFD03D28E}",
	"{3C957E7F-B142-4815-9AC1-484FD15F36A9}"
)

foreach ($guid in $msiGUIDs) {
    Set-ExecutionPolicy -Scope Process Bypass
	Start-Process -FilePath "msiexec.exe" -ArgumentList "/x $guid /qn" -NoNewWindow -Wait
    Start-Sleep -Seconds 2
}

It could be something silly like the GUID not having double quotes around it.
It has quotes around it when you define it in your array, but that tells PowerShell that it’s a string. When you later cast the variable inside of double quotes to satisfy ArgumentList it’s literally printing this:

"/x $guid /qn"
# becomes
/x {3C957E7F-B142-4815-9AC1-484FD15F36A9} /qn

msiexec may need actual quotes around it.
Try this and see if it works

$msiGUIDs = @(
	"{3C957E7F-B142-4815-9AC1-484FD15F36A9}",
	"{36559883-c400-43f5-8c9e-0853f441b301}",
	"{9487E0E2-95E9-4B9C-802E-BB6CFD03D28E}",
	"{3C957E7F-B142-4815-9AC1-484FD15F36A9}"
)

foreach ($guid in $msiGUIDs) {
    $MSIArg = '/x "{0}" /qn' -f $guid
	Start-Process -FilePath "msiexec.exe" -ArgumentList $MSIArg -NoNewWindow -Wait
    Start-Sleep -Seconds 2
}

I removed the Set-ExecutionPolicy line because it doesn’t do anything in the context of your task.
The method I shared is using something called a Format Operator (the -f) and it’s handy for allowing you to cast strings with some pretty controlled formatting:

'/x "{0}" /qn' -f $guid
# produces output with quotes around the GUID
/x "{3C957E7F-B142-4815-9AC1-484FD15F36A9}" /qn
1 Like

Another way if you want to do it inline is escape the inner quotes

$MSIArg = "/x `"$guid`" /qn"

I do this on all my msi file and log paths, in case they contain spaces or special characters

$MsiParams = @{
    FilePath     = 'msiexec.exe'

    ArgumentList = "/I",
                    "`"$MSI_File`"",
                    "/qn",
                    "/norestart",
                    "/L",
                    "`"$locallog`""

    PassThru     = [switch]::Present

    Wait         = [switch]::Present
}
3 Likes

this is great @krzydoug I hadn’t seen it done this way and I think it’s a lot more accessible looking for people than doing the format operator.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.