Hello Don and the greats of PowerShell.
I’m trying to figure out what is wrong with one of my first full PowerShell functions. I want to gather several WMI properties from remote workstations. As usual, most workstations in an environment are never perfect 100%. So with this we may have some workstations which we can ping. However due to services being disabled or rights, we get the dreaded RPC error.
What is strange about my function is that before each RPC error – it adds a space or entry before. I can see this if I output only to the shell or Export-Csv. I’m trying to stop this behavior so I don’t have gaps (rows) within my Csv.
Thanks for all your help and what you do for the community. It really makes a difference!
-Ken
Function Test-WMI {
<#
.SYNOPSIS
Gather WMI from remote workstation(s)
.DESCRIPTION
This function can accept workstation(s) directly on the command or via pipeline. It will then ping (Test-Connection) an gather WMI data.
This WMI data will be temporary put into a hash table and output to an object. This can also be piped to Export-Csv.
.EXAMPLE
Test-WMI ZW650DTS
Description
-----------
Particular workstation times out. This workstations breaks the script, but works fine normally.
.EXAMPLE
Test-WMI -ComputerName ZW650DTS, DW65521H, WIN7ENTX86 -Verbose
Description
-----------
Multiple ComputerName
.EXAMPLE
Get-Content Computers.txt | Test-WMI -Verbose
Description
-----------
Using pipeline from file
.EXAMPLE
Test-WMI -Host DW65521H, WIN7ENTX86
Description
-----------
Using alias
.EXAMPLE
Get-ADComputer -Filter {Name -like "DW6500*"} | Select-Object @{Name='ComputerName';Expression={$_.name}} | Test-WMI -Verbose | Export-Csv -Path .\Output.csv -Encoding ASCII -NoTypeInformation
Description
-----------
Using pipeline with property name change
#>
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
Param (
[Parameter(Mandatory=$False,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]
[Alias('HostName','Workstation')]
[ValidateLength(5,20)]
[string[]]$ComputerName = $env:COMPUTERNAME
)
BEGIN {
}
PROCESS {
foreach ($Computer in $ComputerName) {
Write-Verbose "$Computer gathering data"
$Properties = @{'ComputerName'=$Computer}
If (Test-Connection -ComputerName $Computer -Count 1 -Quiet -BufferSize 16) {
$Properties.Add('PS_Ping',"Passed")
$Win32_OperatingSystem = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer -ErrorVariable myError -ErrorAction SilentlyContinue
$Win32_ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Computer -ErrorVariable myError -ErrorAction SilentlyContinue
$Win32_NetworkAdapterConfiguration = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $Computer -ErrorVariable myError -ErrorAction SilentlyContinue `
| Where-Object {$_.IPEnabled -eq "True"}
If ($myError -ne $null) {
Write-Verbose $myError.Exception.Message | Out-String
$Properties.Add('WMI_Connection',$myError.Exception.Message)
}
Else {
$Properties.Add('WMI_Connection',"Passed")
$Properties.Add('WMI_OS',$Win32_OperatingSystem.Caption)
$Properties.Add('WMI_ServicePack',$Win32_OperatingSystem.CSDVersion)
$Properties.Add('WMI_Manufacturer',$Win32_ComputerSystem.Manufacturer)
$Properties.Add('WMI_Model',$Win32_ComputerSystem.Model)
$Properties.Add('WMI_UserName',$Win32_ComputerSystem.UserName) #null for RDP sessions
$Properties.Add('WMI_IPAddress',$Win32_NetworkAdapterConfiguration.IPAddress[0])
}
}
Else {
Write-Verbose "$Computer failed Test-Connection"
$Properties.Add('PS_Ping',"Failed")
}
$Obj = New-Object -TypeName PSObject -Property $Properties | Select-Object -Property `
ComputerName,
PS_Ping,
WMI_Connection,
WMI_OS,
WMI_ServicePack,
WMI_Manufacturer,
WMI_Model,
WMI_UserName,
WMI_IPAddress
Write-Output $Obj
}
}
END {
}
}