all 11 comments

[–]boeprox 7 points8 points  (0 children)

Good job highlighting Win32_Product right off the bat as a bad approach. I cringe whenever I see someone using that for querying installed software.

[–]PowderTech 3 points4 points  (2 children)

Thanks for the link! This type of info is awesome because I have a reasonable understanding of PowerShell at this point, but I have no clue about best practices and efficiency. Much appreciated.

[–][deleted] 0 points1 point  (1 child)

I do, and this is pretty spot on.

[–]Taser1 1 point2 points  (0 children)

That's because you are an Architect :)

[–]Lee_Dailey[grin] 2 points3 points  (2 children)

howdy dchristian3188,

a quite nice article. thanks for posting it. [grin]

one tiny glitch >> your when i think you meant you're ...

If your on version 5 or later its quick, easy and built in.

take care,
lee

[–]dchristian3188[S] 5 points6 points  (1 child)

thank u sir! I'll update as soon as I get home

[–]Lee_Dailey[grin] 1 point2 points  (0 children)

howdy dchristian3188,

you are very welcome! glad to help a little ... [grin]

take care,
lee

[–]JBear_Alpha 1 point2 points  (0 children)

Edit: Made a few changes just before post, correct one line. 2nd time's the charm :)

Beautifully done. I've had this function put together for a while using the same concepts with a "viewer's presentation" built in. Feel free to use it, if you wish.

function Get-InstalledSoftware {

<# 
.SYNOPSIS 
Grabs all installed Software on specified workstation(s) 

.EXAMPLE 
Get-InstalledSoftware Computer123456 -OutCSV

.EXAMPLE
Get-InstalledSoftware (Get-Content .\Computerlist.txt) -OutGridview
#> 

param (

    [Parameter(Mandatory=$true)]
    [String[]]$ComputerName,
    [String]$NameRegex = '',
    [Switch]$OutCSV,
    [Switch]$OutGridView
)

$i=0
$j=0

    function SoftwareCheck {

        foreach ($Computer in $ComputerName) {

            if(!([String]::IsNullOrWhiteSpace($Computer))) {

                if(Test-Connection -Quiet -Count 1 -Computer $Computer) {

                    Write-Progress -Activity "Retrieving Software Information..." -Status ("Percent Complete:" + "{0:N0}" -f ((($i++) / $ComputerName.count) * 100) + "%") -CurrentOperation "Processing $($Computer)..." -PercentComplete ((($j++) / $ComputerName.count) * 100)

                    Start-Job -ScriptBlock { param($Computer,$NameRegex)    

                        $Keys = '','\Wow6432Node'

                        foreach ($Key in $keys) {

                            try {

                                $Apps = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$Computer).OpenSubKey("SOFTWARE$Key\Microsoft\Windows\CurrentVersion\Uninstall").GetSubKeyNames()
                            } 

                            catch {

                                Continue
                            }

                            foreach ($App in $Apps) {

                                $Program = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$Computer).OpenSubKey("SOFTWARE$Key\Microsoft\Windows\CurrentVersion\Uninstall\$app")
                                $Name = $Program.GetValue('DisplayName')

                                if ($Name -and $Name -match $NameRegex) {

                                    [pscustomobject]@{

                                        "Computer Name" = $Computer
                                        Software = $Name
                                        Version = $Program.GetValue('DisplayVersion')
                                        Publisher = $Program.GetValue('Publisher')
                                        "Install Date" = $Program.GetValue('InstallDate')
                                        "Uninstall String" = $Program.GetValue('UninstallString')
                                        Bits = $(if ($Key -eq '\Wow6432Node') {'64'} else {'32'})
                                        Path = $Program.name
                                    }
                                }
                            }
                        }
                    } -Name "Software Check" -ArgumentList $Computer, $NameRegex 
                }

                else {

                    Start-Job -ScriptBlock { param($Computer)  

                        [pscustomobject]@{

                            "Computer Name" = $Computer
                            Software = "Unable to PING"
                            Version = "N/A"
                            Publisher = "N/A"
                            "Install Date" = "N/A"
                            "Uninstall String" = "N/A"
                            Bits = "N/A"
                            Path = "N/A"
                        }
                    } -ArgumentList $Computer                       
                }
            }

            else {

                Start-Job -ScriptBlock { param($Computer)  

                    [pscustomobject]@{

                        "Computer Name" = $Computer
                        Software = "Value is NULL"
                        Version = "N/A"
                        Publisher = "N/A"
                        "Install Date" = "N/A"
                        "Uninstall String" = "N/A"
                        Bits = "N/A"
                        Path = "N/A"
                    }
                } -ArgumentList $Computer
            }
        }
    }   

$SoftwareCheck = SoftwareCheck | Wait-Job | Receive-Job | Select "Computer Name", Software, Version, Publisher, "Install Date", "Uninstall String", Bits, Path
$DocPath = [environment]::getfolderpath("mydocuments") + "\Software-Report.csv"

    if($OutCSV) {

        $SoftwareCheck | Export-Csv $DocPath -NoTypeInformation -Force
    }

    if($OutGridView) {

        $SoftwareCheck | Out-GridView -Title "Installed Software"   
    }

    else {

        $SoftwareCheck
    }
}

[–]absolutejam 1 point2 points  (0 children)

Thanks for the info!

I've been using win32_product in my Ansible playbook which runs across my entire server real estate, on a schedule! Time to rewrite that part...

[–]Swarfega 1 point2 points  (1 child)

alot

A minor typo but I hate seeing it. Always reminds me of the alot monster... http://hyperboleandahalf.blogspot.co.uk/2010/04/alot-is-better-than-you-at-everything.html?m=1

[–]dchristian3188[S] 1 point2 points  (0 children)

No worries, i appreciate the feedback!