It has been a long time that I have not been posting anything new on this blog. That does not mean that I am not working on anything fancy to ease an administrator daily operation in providing organization the appropriate information for decision making in finding out the amount of software installed within the organization infrastructure.
Software utilisation is an issue in any organization and those licenses involve cost. I came up with this Get-Product PowerShell CMDLET to ease my workload in finding out the information during March 2013 and is releasing it in TechNet Gallery for everyone today.
Sorry for the delay in releasing this Get-Product CMDLET, I was too busy with my workload and it just happen that I’m on a holiday break today to find time to post. Hope it is not too late to assist the administrators out there.
Download Link – http://gallery.technet.microsoft.com/Get-Product-8da22470
Get-Product Cmdlet has been updated to Version 2.0
– The Download link above will redirect you to Get-Product version 2.0 in TechNet Gallery
– Find out Get-Product version 2.0 improvements and bug fixes – Read More
– The PowerShell code below for Version 1.0 is buggy.
function Get-Product { <# .SYNOPSIS Get product installed within the host to a CSV file .DESCRIPTION Allow Administrators to query WMI namespace on installed product and determine the number of host with the product in the Domain. .PARAMETER ComputerName This parameter allows you to input a specific hostname. .PARAMETER Domain This parameter allows you to scan the computers within the domain. .PARAMETER Caption This parameter allows you to filter the output for the specified caption. .PARAMETER Description This parameter allows you to filter the output for the specified description. .PARAMETER InstallDate This parameter allows you to filter the output for the specified install date. .PARAMETER InstallLocation This parameter allows you to filter the output for the specified install location. .PARAMETER Name This parameter allows you to filter the output for the specified name. .PARAMETER Vendor This parameter allows you to filter the output for the specified vendor. .PARAMETER Version This parameter allows you to filter the output for the specified version. .PARAMETER CSVOutput This parameter allows you to specify the csv output location for the result. EXAMPLE: Get-Product -CSVOutput C:\Temp\Get-Product_Result.csv .PARAMETER ErrorOutput This parameter allows you to specify the csv output location for the errors. EXAMPLE: Get-Product -ErrorOutput C:\Temp\Get-Product_Errors.csv .OUTPUT By default, the Get-Product output is returned to the screen. In this Get-Product CMDLET, there is two type of output. One is to out the result as a CSV file using the -CSVOutput PARAMETER. Another is to output any errors to a CSV file using the -ErrorOutput PARAMETER. .NOTES Author : Ryen Kia Zhi Tang Date : 06/03/2013 Blog : ryentang.wordpress.com Version : 1.0 #> [CmdletBinding( SupportsShouldProcess=$True, ConfirmImpact='High')] param ( [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $ComputerName = $Env:ComputerName, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [Switch] $Domain, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $Caption, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $Description, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $InstallDate, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $InstallLocation, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $Name, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $Vendor, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $Version, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $CSVOutput, [Parameter( Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [String] $ErrorOutput ) BEGIN {} PROCESS { $ErrorActionPreference = "SilentlyContinue" #create an object to store data $Object = New-Object PSObject $Result = @() $Errors = @() if($Domain) { #create directory entry object $objDomain = New-Object System.DirectoryServices.DirectoryEntry #create directory searcher object $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objSearcher.SearchRoot = $objDomain #input custom filter $objSearcher.Filter = ("(&(objectCategory=Computer)(operatingSystem=Windows Server *))") if($PSBoundParameters['Verbose']) { Write-Verbose "Scanning the Domain..." } #get properties $propertieslist = "*" foreach ($i in $propertieslist){$objSearcher.PropertiesToLoad.Add($i)} $items = $objSearcher.FindAll() $totalComputerObject = $($items | Measure-Object | %{$_.Count}) $counterComputerObject = 1 foreach($item in $items) { $item = $item.Properties $ComputerName = [string] $item.name if($PSBoundParameters['Verbose']) { Write-Verbose "Checking $ComputerName for Product..." } Write-Progress -Id 0 -Activity "Scanning the Domain..." -Status "Found $ComputerName" -PercentComplete ($counterComputerObject++ / $totalComputerObject*100) -CurrentOperation "Establishing Connection..." $Object = Find-Product $ComputerName $Caption $Description $InstallDate $InstallLocation $Name $Vendor $Version if($Object.ErrorCode -eq $null) { $Result += $Object }else{ $Errors += $Object } } }else{ if($PSBoundParameters['Verbose']) { Write-Verbose "Checking $ComputerName for Product..." } $Object = Find-Product $ComputerName $Caption $Description $InstallDate $InstallLocation $Name $Vendor $Version if($Object.ErrorCode -eq $null) { $Result += $Object }else{ $Errors += $Object } } } END { if($CSVOutput -eq "") { $Result }else{ $Result | Export-Csv -Path $CSVOutput -NoTypeInformation -Force } if($ErrorOutput -eq "") { $Errors }else{ $Errors | Export-Csv -Path $ErrorOutput -NoTypeInformation -Force } if($PSBoundParameters['Verbose']) { Write-Verbose "Done!!!" } } } function Find-Product($ComputerName, $Caption, $Description, $InstallDate, $InstallLocation, $Name, $Vendor, $Version) { BEGIN {} PROCESS { $Result = @() $Object = gwmi -ComputerName $ComputerName -Class Win32_Product -Impersonation Impersonate -Authentication PacketPrivacy -ErrorVariable err | Select-Object * if($err) { if($PSBoundParameters['Verbose']) { Write-Host $err -ForegroundColor Red } $OperatingSystem = gwmi -ComputerName $ComputerName -Class Win32_OperatingSystem -Impersonation Impersonate -Authentication PacketPrivacy -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Caption #create an object to store data $error = New-Object PSObject $error | Add-Member -MemberType noteproperty -Name "__SERVER" -Value $ComputerName $error | Add-Member -MemberType noteproperty -Name "OperatingSystem" -Value $OperatingSystem $error | Add-Member -MemberType noteproperty -Name "ErrorCode" -Value $($err | Select -ExpandProperty Exception).ErrorCode $error | Add-Member -MemberType noteproperty -Name "Message" -Value $($err | Select -ExpandProperty Exception).Message return $error }else{ $totalInstalledProduct = $($Object | Measure-Object | %{$_.Count}) $counterInstalledProduct = 1 foreach($item in $Object) { Write-Progress -Id 1 -ParentId 0 -Activity "Scanning $ComputerName..." -Status "Checking All Programs" -PercentComplete ($counterInstalledProduct++ / $totalInstalledProduct*100) -CurrentOperation "Checking installed product: $($item | Select -ExpandProperty Name)" if($($item | Select -ExpandProperty Caption) -like $Caption) { $Result += $item }elseif($($item | Select -ExpandProperty Description) -like $Description) { $Result += $item }elseif($($item | Select -ExpandProperty InstallDate) -like $InstallDate) { $Result += $item }elseif($item.InstallLocation -ne $null) { if($($item | Select -ExpandProperty InstallLocation) -like $InstallLocation) { $Result += $item } }elseif($($item | Select -ExpandProperty Name) -like $Name) { $Result += $item }elseif($($item | Select -ExpandProperty Vendor) -like $Vendor) { $Result += $item }elseif($($item | Select -ExpandProperty Version) -like $Version) { $Result += $item }elseif($Caption -eq "" -and $Description -eq "" -and $InstallDate -eq "" -and $InstallLocation -eq "" -and $Name -eq "" -and $Vendor -eq "" -and $Version -eq ""){ $Result += $item } } Write-Progress -Id 1 -ParentId 0 -Activity "Scanning $ComputerName..." -Status "Completed" -Completed } } END { return $Result } } Export-ModuleMember -Function Get-Product