Get-Product PowerShell CMDLET

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

Advertisements