function Get-MachineInventory { <# .SYNOPSIS Returns an Object that Represents the State of a Machine .DESCRIPTION Executes multiple collectors which describe the state of a machine. Can execute on an array of machine names or PSSessions and allows for an optional filter to be included. May be returned as a PSObject, JSON, or XML .PARAMETER TargetComputerNames [string[]] One or more remote computers to profile .PARAMETER PsSessions [PSSession[]] One or more PSSessions to Use .PARAMETER Filter [string[]] A filter which limits the number of profilers to execute .PARAMETER JsonOutput [switch] Specifies to return the result as JSON .PARAMETER XmlOutput [switch] Specifies to return the result as XML .INPUTS None .OUTPUTS An object with details about the machine state. May be a PSObject (default), JSON, or XML depending on arguments .EXAMPLE Get-MachineInventory [Get-MachineInventory] : Collecting data from 1 target(s) WARNING: [ALKA01VMA167] : Function Get-AppSettingsInventory Took 00:00:02.2702503 to Execute [Get-MachineInventory] : Received 1 result(s) [Get-MachineInventory] : Adding Results for ALKA01VMA167 [Get-MachineInventory] : Inventory Collection Complete After 00:00:07.9261976 Name Value ---- ----- ALKA01VMA167 {OS, Version, Architecture, GenerationTime...} .EXAMPLE Get-MachineInventory -Filter Uptime, FileSystem [Get-MachineInventory] : Collecting data from 1 target(s) [Get-MachineInventory] : Received 1 result(s) [Get-MachineInventory] : Adding Results for ALK-DELL1323 Name Value ---- ----- ALK-DELL1323 {OS, Version, Architecture, GenerationTime...} .EXAMPLE Get-MachineInventory -Filter Uptime -MachineNames @("localhost", "ALKA01VMA163.fh.local") [Get-MachineInventory] : Collecting data from 2 target(s) [Get-MachineInventory] : Received 2 result(s) [Get-MachineInventory] : Adding Results for ALKA01VMA163 [Get-MachineInventory] : Adding Results for ALK-DELL1323 Name Value ---- ----- ALKA01VMA163 {OS, Version, Architecture, GenerationTime...} ALK-DELL1323 {OS, Version, Architecture, GenerationTime...} #> [CmdletBinding(DefaultParameterSetName = 'FilterOnlyParameterSet')] [OutputType([string], ParameterSetName=("MachineNameParameterJson","SessionParameterJson","FilterParameterSetJson"))] [OutputType([System.Xml.XmlDocument], ParameterSetName=("MachineNameParameterXml","SessionParameterXml","FilterParameterSetXml"))] [OutputType([System.Collections.Specialized.OrderedDictionary], ParameterSetName=("MachineNameParameterSet","SessionParameterSet"))] param( [Parameter(ParameterSetName = 'MachineNameParameterSet', Mandatory = $true)] [Parameter(ParameterSetName = 'MachineNameParameterJson', Mandatory = $true)] [Parameter(ParameterSetName = 'MachineNameParameterXml', Mandatory = $true)] [Alias("ComputerNames", "Servers", "MachineNames")] [string[]]$TargetComputerNames, [Parameter(ParameterSetName='SessionParameterSet', Mandatory=$true)] [Parameter(ParameterSetName='SessionParameterJson', Mandatory=$true)] [Parameter(ParameterSetName='SessionParameterXml', Mandatory=$true)] [Alias("Sessions")] [System.Management.Automation.Runspaces.PSSession[]]$PsSessions, [Parameter(ParameterSetName = 'MachineNameParameterJson', Mandatory = $true)] [Parameter(ParameterSetName = 'SessionParameterJson', Mandatory = $true)] [Parameter(ParameterSetName = 'FilterParameterSetJson', Mandatory = $false)] [Alias("JsonOutput")] [switch]$AsJson, [Parameter(ParameterSetName = 'MachineNameParameterXml', Mandatory = $true)] [Parameter(ParameterSetName = 'SessionParameterXml', Mandatory = $true)] [Parameter(ParameterSetName = 'FilterParameterSetXml', Mandatory = $false)] [Alias("XMLOutput")] [switch]$AsXML ) DynamicParam { # Define the Paramater Attributes $ParameterName = "Filter" $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute $ParameterAttribute.Mandatory = $false $ParameterAttribute.ParameterSetName = "__AllParameterSets" $AttributeCollection.Add($ParameterAttribute) # Generate and add the ValidateSet $arrSet = $inventoryFilterSetOptions | ForEach-Object { $_.FilterName } $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) $AttributeCollection.Add($ValidateSetAttribute) # Create the dynamic parameter $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string[]], $AttributeCollection) $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) return $RuntimeParameterDictionary } begin { # Bind the Filter dynamic parameter to a variable $logLead = Get-LogLeadName Write-Host "$logLead : Executing using ParameterSet: [$($PSCmdlet.ParameterSetName)]" $filterCollection = $PsBoundParameters[$ParameterName] Write-Host "$logLead : Executing with filters: [$filterCollection]" # We'll Silently Continue for Any Provider Errors -- They Get Added to the Results $originalErrorActionPreference = $ErrorActionPreference $ErrorActionPreference = "SilentlyContinue" $functionStopWatch = [System.Diagnostics.StopWatch]::StartNew() $inventoryResult = New-Object System.Collections.Specialized.OrderedDictionary } process { try { $clearSessions = $true if ($null -eq $PsSessions -or $PsSessions.Count -eq 0) { $sessions = @() foreach ($target in $TargetComputerNames) { Write-Host "$logLead : Creating Session for $target" $sessions += New-PSSession -ComputerName $target -ErrorVariable err -ErrorAction SilentlyContinue if($err.Count -gt 0) { Write-Warning "$logLead : New-PSSession encountered an error : $err" } } } else { $clearSessions = $false $sessions = $PsSessions } $scriptBlock = { $logLead = "[$env:COMPUTERNAME]" $ErrorActionPreference = "Continue" $machineData = New-Object System.Collections.Specialized.OrderedDictionary $uniqueSections = $Using:inventoryFilterSetOptions | ForEach-Object { $_.SectionVariable } | Sort-Object | Select-Object -Unique $VerbosePreference=$Using:VerbosePreference; foreach ($section in $uniqueSections) { Write-Verbose "$logLead : Creating Variable for $section Data" New-Variable -Name $section -Value (New-Object System.Collections.Specialized.OrderedDictionary) } # Always include Platform Inventory as Top Level Properties $machineData += Get-PlatformInventory # Use the entire filter set if no filter was set as a parameter [array]$filteredInventories = Test-IsNull $Using:filterCollection ($Using:inventoryFilterSetOptions | ForEach-Object { $_.FilterName }) -Strict Write-Verbose "$logLead : Using Final Inventory Filter: [$filteredInventories]" foreach ($inventory in ($filteredInventories | Sort-Object)) { $matchingFilter = $Using:inventoryFilterSetOptions | Where-Object {$_.FilterName -eq $inventory} $masterProviderStopWatch = [System.Diagnostics.StopWatch]::StartNew() Write-Host "$logLead : Executing FunctionName [$($matchingFilter.FunctionName)]" $sb = [ScriptBlock]::Create($matchingFilter.FunctionName) ((Get-Variable -Name $matchingFilter.SectionVariable).Value) += (Invoke-Command $sb) $masterProviderStopWatch.Stop() if ($masterProviderStopWatch.ElapsedMilliseconds -ge 1000) { Write-Warning "$logLead : Function $($matchingFilter.FunctionName) Took $($masterProviderStopWatch.Elapsed) to Execute" } } foreach ($uniqueSection in $uniqueSections) { $section = (Get-Variable -Name $uniqueSection -ValueOnly) if ($section.Count -gt 0) { Write-Verbose "$logLead : Adding $uniqueSection Section to Results" $machineData.Add("$uniqueSection", $section) } } return $machineData } Write-Host "$logLead : Collecting data from $($sessions.Count) target(s)" [array]$results = Invoke-Command -ScriptBlock $scriptBlock -Session $sessions Write-Host "$logLead : Received $($results.Count) result(s)" # Add Result Sets foreach ($result in $results) { Write-Host "$logLead : Adding Results for $($result.Hostname)" $inventoryResult.Add($result.Hostname, $result) } } finally { Write-Host "$logLead : Setting ErrorActionPreference to $originalErrorActionPreference" $ErrorActionPreference = $originalErrorActionPreference if ($clearSessions) { if ($sessions.Count -gt 0) { Write-Host "$logLead : Cleaning Up PSSessions" Remove-PSSession $sessions; } else { Write-Error "$logLead : WinRM cannot connect to any computers in the input list." } } } $functionStopWatch.Stop() Write-Host "$logLead : Inventory Collection Complete After $($functionStopWatch.Elapsed)" if ($AsJson) { return ($inventoryResult | ConvertTo-Json -Depth 8) } if ($AsXml) { return ($inventoryResult | ConvertTo-Xml -Depth 8 -As Document) } return $inventoryResult } }