Invoking Registry UninstallString

Goal: leverage powershell to query registry for uninstallstring for specific software. Once uninstallstring is known, invoke uninstallstring to remove application.

We have a Silverlight Out-Of-Browser application that needs uninstalled on 500+ systems.

The script:
#################
###Sets location to software file location in user profile
Set-Location -Path “c:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0”

###Sets variable for reg HKCU query, filters for sloobapp, displays displayname, uninstallstring properties
$apsInst = Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall|
Get-ItemProperty|Where-Object {$_.DisplayName -match “sloobapp” }|
Select-Object -Property DisplayName, UninstallString

###For each match, run the registry uninstall string
ForEach ($sloobapp in $apsInst) {

    If ($sloobapp.UninstallString) {

        $uninst = $sloobapp.UninstallString
        }

###########

As for my problem, when ran it just prints the variable on screen. “$uninst” , now I believe my laymaness is being exhibited and I have not properly formatted the “” section above. Any thoughts/Suggestions?

Apologies, should read the bulletins, parts of my above message are missing. I’ve attached a txt.

As for my problem, when ran it just prints the variable on screen. “$uninst” , now I believe my laymaness is being exhibited and I have not properly formatted lines 14 & 15 .

Replace

& cmd /c {'.$uninst'}

with

& $uninst

or

Start-Process -FilePath cmd.exe -ArgumentList '/c', $uninst -Wait

Daniel,

Very much appreciated, your recommendation “start-process” worked!

It seems perhaps the issue is lines 12-14, as when I run the command “Silverlight.Configuration.exe -uninstallApp sloobapp” is ran at “C:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0>” it uninstalls the application with no issues.

But when we call the variable “$uninst” in the script it does not uninstall the application. Now I thought I’d resolve this issue by setting the location to the “C:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0>” , but that did not seem to help.

Any thoughts?

How are you setting the location and when? Did you use Set-Location (CD) during script execution or change the directory of the Powershell prompt and then run the script? Do you get the expected results if you prepend the path for the EXE?

$uninst = "C:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0\{0}" -f $uninst

or

Set-Location "C:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0" 
Start-Process -FilePath cmd.exe -ArgumentList '/c', $uninst -Wait

Previously, I’ve set the location prior to script execution with the “Set-Location” cmdlet. I’ve since moved the set-location to line 13.
The script processes, but still $uninst variable is not performing as if I run “Silverlight.Configuration.exe -uninstallApp sloobapp” straight at the command line.

Now I believe this is happening because on line 11 i’m setting “$uninst = ($aps.UninstallString)” which is the registry uninstall string pulled from the key above. I’m attempting to run it in this variable.

(pre){{###Sets variable for reg HKCU query, filters for SLOOBAPP, displays displayname, uninstallstring properties
$apsInst = Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall|
Get-ItemProperty|Where-Object {$_.DisplayName -match “SLOOBAPP”}
Select-Object -Property DisplayName, UninstallString

ForEach ($aps in $apsInst) {
    
    If ($aps.UninstallString) {

 $uninst = $aps.UninstallString
       
        Set-Location -Path "c:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0"

        Start-Process -FilePath cmd.exe -ArgumentList '/c', $uninst -wait
}

}} (/pre)

So with everyone’s assistance I was able to get this to actually work, as expected, now I need to make this work on 500+ computers

(pre){#Set variable for registry query, where Any match of “HCI APS”, Select property “UninstallString” - Working
$apsInst = Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall|
Get-ItemProperty | Where-Object {$_.DisplayName -match “SLOOBAPP”}|
Select-Object -Property UninstallString

$uninst = “Silverlight.Configuration.exe -uninstallApp 165905322.SLOOBAPP.somewebsite.com

ForEach ($aps in $apsInst) {

If ($aps.UninstallString){
   
   Set-Location -Path "c:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0"
   
   Start-Process -FilePath cmd.exe -ArgumentList '/c', $uninst -wait 
}

} }(/pre)

So continuing from above.
I believe I’ll need to take the “UninstallString” value and plug it in on the fly into the $uninst variable for this to work on any system I’d like to use it on.
As the number that precedes “xxxxxxxxx.sloobapp.somewebsite.com” is a randomly generated integer that can be any integer 0-9 of any length.

I’m kind of at a loss how to do this, originally I was thinking I’d have to utilize a regular expression to account for the unique integer string preceding the webclient.

Thoughts or Suggestions?

I was wondering about this earlier when I looked at it but you said you had it working. You connect to registry, find the uninstall string and then use a manual uninstall string. Take a look at this and see if you understand the logic:

function Get-InstalledApps {
param()
    begin{}
    process{
        $apps = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* |
                Select DisplayName, 
                DisplayVersion, 
                UnInstallString,
                InstallDate,
                @{Name="VERSION_MAJOR";Expression={($_.DisplayVersion.Split("."))[0]}},
                @{Name="VERSION_MINOR";Expression={($_.DisplayVersion.Split("."))[1]}},
                @{Name="VERSION_REVISION";Expression={($_.DisplayVersion.Split("."))[2]}},
                @{Name="VERSION_BUILD";Expression={($_.DisplayVersion.Split("."))[3]}}, 
                @{Name="GUID";Expression={$_.PSChildName}},
                @{Name="AppArchitecture";Expression={"86"}}
        # If it is a 64-bit box, then also include the Wow6432Node
        if((Get-WmiObject Win32_Processor).AddressWidth -eq 64){
            $apps += Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | 
                     Select DisplayName,
                     DisplayVersion, 
                     UnInstallString,
                     InstallDate, 
                     @{Name="VERSION_MAJOR";Expression={($_.DisplayVersion.Split("."))[0]}},
                     @{Name="VERSION_MINOR";Expression={($_.DisplayVersion.Split("."))[1]}},
                     @{Name="VERSION_REVISION";Expression={($_.DisplayVersion.Split("."))[2]}},
                     @{Name="VERSION_BUILD";Expression={($_.DisplayVersion.Split("."))[3]}}, 
                     @{Name="GUID";Expression={$_.PSChildName}}, 
                     @{Name="AppArchitecture";Expression={"64"}}
        }

        $apps | Where{ !([string]::IsNullOrEmpty($_.DisplayName)) }
    }
    end{}
}

# Get all 32\64 bit applications
$installedApps = Get-InstalledApps
# Find any application with SLOOBAPP in the name
$silverLight = $installedApps | Where-Object {$_.DisplayName -match "SLOOBAPP"}

#If an application was found (variable not null)...
if ($silverLight) {
    foreach ($application in $installedApps) {
        #if the uninstall string is not null...
        If ($application.UninstallString){
            #Here you are specifying (x86) only, so this would fail if there were a 64-bit Silverlight installation
            #You should use similar logic I'm using in the function above to see if it's a 64-bit machine or I'm adding
            #an AppArchitecture param, so you could do if ($application.AppArchitecture -eq 32){"Set location for 32}else{Set Location for 64}
            Set-Location -Path "c:\Program Files (x86)\Microsoft Silverlight\5.1.30514.0"
            #Rather than use a manual string (e.g. $uninst, you would just reference
            "Running command: {0} from {1}" -f $application.UninstallString, (Get-Location)
            Start-Process -FilePath cmd.exe -ArgumentList '/c', $application.UninstallString -wait
        }
        else {
            "There is not uninstall string for {0}" -f $application.DisplayName
        } #if UnInstallString
    } #for each application
}
else {
    "Silverlight is not installed."
} #if $silverlight

Thank you both for your time. I was able to enumerate all the applications installed using your methods.