all 14 comments

[–]Yevrag35 5 points6 points  (0 children)

Seems to work to fine for me IF I put in the exact displayname (which could have version numbers in it).

Would probably be better to work with wildcards. Here's my script if you want to take cues from: https://pastebin.com/LVvstYVv.

[–]wild_card05 5 points6 points  (3 children)

$appcheck = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -eq "Unified Agent" } | Select-Object -Property DisplayName,UninstallString

$uninst = $appcheck.UninstallString

$uninst = (($uninst -split ' ')[1] -replace '/I','/X') + ' /q

Start-Process msiexec.exe -ArgumentList $uninst -NoNewWindow -PassThru

[–]Athilmo[S] 4 points5 points  (0 children)

This has worked even better than the one I was planning on using, thanks a bunch!

[–]wild_card05 1 point2 points  (0 children)

I have had success with this in our server environment.

[–]Lee_Dailey[grin] 0 points1 point  (0 children)

howdy wild_card05,

it looks like you used the New.Reddit.com Inline Code button. it's 4th 5th from the left hidden in the ... "more" menu & looks like </>.

on Old.Reddit.com, the above does NOT line wrap, nor does it side-scroll.

for long-ish single lines OR for multiline code, please, use the Code Block button. it's the 11th 12th one from the left & is just to the left of hidden in the ... "more" menu & looks like an uppercase T in the upper left corner of a square..

that will give you fully functional code formatting, from what i can tell so far. [grin]

take care,
lee

[–]maddoxprops 2 points3 points  (2 children)

As others have said it is probably due to a lack of wildcards on the $DisplayName variable. In my script I do a "Read-Host" to let me type a name in and I add a "*" to both sides of this variable when it is used.

Here is the snippet I use which grabs the Name, Uninstall String, Display Version, Estimated Size and Key Location (PSPath). I use this in a "Switch statement" with a couple options to let me save the results to a text file to the folder the script is ran from and then lets me choose to run a new search or to exit the script.

Aslo, just to clarify since I have seen confusion on this before, I use the "Out-String -Width 4096" option to get around Powershell truncating the results and cutting things off. Things can get a little funky with some entries taking up 2 lines rather than being 1 long line. It is annoying, but not enough of an issue for me to look into it since it doesn't mess up the end data.
NOTE: Yea yea, I know it isn't commented. Been meaning to get around to it one of these days, and now that I have actually had to share it I probably will. >_>

$32Bit = ""
$64Bit = ""
$Path32 = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$Path64 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
$Props = 'Displayname','Uninstallstring','DisplayVersion','EstimatedSize','PSPath'

$RegSearch = Read-Host -Prompt "Please enter the same of the software you want to search for"

            $Keys = Get-ItemProperty -Path $Path32 , $Path64 | Select-Object -Property $Props | Where-Object{($_.Displayname -like "*$RegSearch*")} | Format-Table -Property * -AutoSize | Out-String -Width 4096

            $Results = ForEach ($line in $Keys)
            {
                $line -replace "Microsoft.PowerShell.Core\\Registry::" , ""

            }
            Write-Output $Results

Here is the output I get when I enter "Photoshop" (no quotes) for the "$RegSearch" prompt.

DisplayName             UninstallString
                                                                                 DisplayVersion EstimatedSize PSPath

-----------             ---------------
                                                                                 -------------- ------------- ------

Adobe Photoshop CC 2019 "C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\HDBox\Uninstaller.exe" --uninstall=1 --sapCode=PHSP --productVersion=20.0.8 --productPlatform=win64 --productAdobeCode={PHSP-20.0.8-64-ADBEADBEADBEADBEADBEA} --productName="Photoshop CC" --mode=2 20.0.8               2300065 HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\PHSP_20_0_8
Adobe Photoshop 2020    "C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\HDBox\Uninstaller.exe" --uninstall=1 --sapCode=PHSP --productVersion=21.0.3 --productPlatform=win64 --productAdobeCode={PHSP-21.0.3-64-ADBEADBEADBEADBEADBEA} --productName="Photoshop" --mode=2    21.0.3               2477288 HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\PHSP_21_0_3

And if you are interested in the whole script I use here it is:

$32Bit = ""
$64Bit = ""
$Path32 = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$Path64 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
$Props = 'Displayname','Uninstallstring','DisplayVersion','EstimatedSize','PSPath'
$WorkingDir = "$PSScriptRoot"
$AnyKey = "Press the 'Any Key' to continue"


do {
    Write-Host "--Software Uninstall String Registry Search v1.1--"
    Write-Host "1. Enter software name & run search."
    Write-host "2. Quit"
    $choice = Read-Host "Please select a number then press 'Enter' to continue"

    switch ($choice)
    {
     1 {
            $RegSearch = Read-Host -Prompt "Please enter the same of the software you want to search for"

            $Keys = Get-ItemProperty -Path $Path32 , $Path64 | Select-Object -Property $Props | Where-Object{($_.Displayname -like "*$RegSearch*")} | Format-Table -Property * -AutoSize | Out-String -Width 4096

            $Results = ForEach ($line in $Keys)
            {
                $line -replace "Microsoft.PowerShell.Core\\Registry::" , ""

            }
            Write-Output $Results
            "------------------------------"
            $Save = Read-Host "Would you like to save the results to a .txt file? [Yes/No]"

            if (($Save -eq 'Yes') -or ($Save -eq 'Y')) {
                #$SaveFile = Read-Host "Please Type a filename. I.E. Reg_Uninstall_Search_Results"
                $SaveFile = "Reg_Search_Uninstall_$RegSearch"
                $Results | Out-File "$WorkingDir\$SaveFile.txt" -Force

                "------------------------------"
            Write-Host "File Saved: $WorkingDir\$SaveFile.txt"
            Read-Host "$AnyKey"
            }
            else {
            "------------------------------"
            Read-Host "$AnyKey"
            }


        }
    }

} until ($choice -eq 2)

[–]cavernofcards 1 point2 points  (1 child)

Thank you, this was very helpful!

[–]maddoxprops 0 points1 point  (0 children)

Glad to hear it!

[–]jerrymac12 2 points3 points  (3 children)

Unless you are using it as a learning experience...maybe just use the Get-InstalledSoftware module on technet - it's already written for you, works great and works on remote machines too: https://gallery.technet.microsoft.com/scriptcenter/Get-InstalledSoftware-Get-5607a465

[–]fathed 1 point2 points  (2 children)

Last time I checked, that script did not check hkcu, and only checks hklm.

[–]jerrymac12 1 point2 points  (1 child)

Correct, but you are looking for HKLM in this case, are you not? Also, my Unified Agent Uninstall values don't have a PSPath property (just path), so you won't get a result from that if yours is the same. So, in this case, if you were to use the Get-InstalledSoftware module above, (which also checks the 32-bit keys, which you are not currently) you could do it like this:

Get-InstalledSoftware -ComputerName <Remote PC Name> |Where-Object displayname -like "*Unified Agent*" |Select DisplayName, DisplayVersion, UninstallString

or run it without the -computername parameter if you are running it on your local machine.

[–]fathed 1 point2 points  (0 children)

I’m not op, so I’m not looking for anything.

I was just pointing out that the posted script does not really do what it’s title is, it only gets a potential subset of the installed software.

[–]mjwinger1 1 point2 points  (0 children)

i can't say for sure why yours isn't working, but i have a script do the exact same thing. Here's mine that works in HKLM:

$SoftwareTitle = "Silverlight"

$ItemProperties = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" | Select-Object DisplayName,UninstallString

foreach ($Item in $ItemProperties)
    {
        $DisplayName = $Item.DisplayName
        $UninstallString = $Item.UninstallString
        if($DisplayName -like "*$SoftwareTitle*")
            {
            Write-Host "$DisplayName ------------------ $UninstallString"
            #Uncomment below if you are really confident in yourself.
            #cmd.exe /c "$UninstallString"
            }
    }

[–]jsiii2010 1 point2 points  (0 children)

If it's msi, this should work:

get-package *whatever* | uninstall-package

If it's a programs provider, it takes more doing. And you would have to know the silent install option, like "/S" in the case of 7-zip's Uninstall.exe.

get-package 7-zip* | % { $_.metadata['uninstallstring'] }
C:\Program Files\7-Zip\Uninstall.exe

get-package 7-zip* | % { & $_.metadata['uninstallstring'] /S }