I'm having trouble trying to capture, then display the results of Get-NetRoute from within a module:
$option = New-CimSessionOption -Protocol $Protocol
$session = New-CimSession -ComputerName $name -Credential $Credentials -SessionOption $option -ErrorAction $ErrorAct;
$res = Get-NetRoute -CimSession $session
Write-Host $res
What I end up with is garbage:
MSFT_NetRoute (InstanceID = "???8???8???8???9??55?55:8:8:8:55;") MSFT_NetRoute (InstanceID = "???8???8???8???9??55;55:8:8:8:55;") MSFT_NetRoute (InstanceID = "???8:8:8:9?55?55:8:8:8:55;") MSFT_NetRoute (InstanceID = "???8:8:8:9?55;55:8:8:8:55;") MSFT_NetRoute (InstanceID = ";C?8;@B8;8???9??55?55:8:8:8:55;") MSFT_NetRoute (InstanceID = ";C?8;@B8;8?:?9??55?55:8:8:8:55;") MSFT_NetRoute (InstanceID = ";C?8;@B8;8:9??55?55:8:8:8:55;") MSFT_NetRoute (InstanceID = ";?A8???8???8???9??55;55:8:8:8:55;") MSFT_NetRoute (InstanceID = ";?A8:8:8;9??55;55:8:8:8:55;") MSFT_NetRoute (InstanceID = ";?A8:8:8:9B55;55:8:8:8:55;") MSFT_NetRoute (InstanceID = ":8:8:8:9:55?55;C?8;@B8;8;55;") MSFT_NetRoute (InstanceID = "pp::DD9B55?55DD55;") MSFT_NetRoute (InstanceID = "pp::DD9B55;55DD55;") MSFT_NetRoute (InstanceID = "poB:DD?B;CD??plD??oBDA@?:9;?B55?55DD55;...) MSFT_NetRoute (InstanceID = "poB:DD9@?55?55DD55;") MSFT_NetRoute (InstanceID = "DD;9;?B55;55DD55;")
When what I expect is a properly formatted table (or at least properties on the $res object that I can get valid values from.) Ultimately, I want to do a little parsing and add columns from other cmdlets later in the script to give me a full report of network configuration on a remote machine. How can I properly capture the result and have it actually show the data as when I do it directly at the command line? Is it because I have to iterate over $res as in a Foreach-Object to access each row in it's result set?
[Edit: Moved from wrong board]
[Edit2: Here's my code listing]
Function Get-RemoteRouteData{
[CmdletBinding()]
[OutputType([System.Management.Automation.PSCustomObject])]
param (
[Parameter(Mandatory = $true)]
[string]$Subnet,
[Parameter(Mandatory = $true)]
[object]$Credentials,
[Parameter(Mandatory = $false)]
[string]$Protocol = 'WSMan',
[Parameter(Mandatory = $false)]
[bool]$TableOnly,
[Parameter(Mandatory = $false)]
[string]$ErrorAct = 'SilentlyContinue'
)
if (!$TableOnly)
{
Write-Host "Scanning $subnet for hosts..."
}
#Use PSSubnetScan module for hosts
$computers = Get-PSSubnetScan -IPList $subnet -RevDNS -ICMPTest
$out = @() # Holds list of output objects
$time = Measure-Command {
foreach ($computer in $computers)
{
$name = $computer.RevDNS.Hostname
$ip = $computer.IPAddress.IPAddressToString
$ping = $computer.ICMP.IsActive
#Check to see if we have a host name or can ping. If neither, skip it.
if ((!$null -eq $name) -and (!$true -eq $ping))
{
Continue
}
if (!$TableOnly)
{
Write-Host "Asking $name - $ip for it's Routing Table"
}
$session = $null
try
{
#Use WMI Class directly
#([WMIClass]"\\$name\ROOT\CImv2:Win32_Process").Create("cmd.exe /c ipconfig /registerdns") | Out-Null
#([WMIClass]"\\192.168.1.205\ROOT\CImv2:Win32_Process").Create("cmd.exe /c winrm quickconfig"
#Use Cim Session
#$option = New-CimSessionOption -Protocol $Protocol
$session = New-CimSession -ComputerName $name -Credential $Credentials #-SessionOption $option -ErrorVariable $err;
$res = Get-NetRoute -CimSession $session
$res | Format-List -Property *
Write-Host "Sanity Check..."
}
catch
{
if (!$TableOnly)
{
Write-Host "$ip - $name - FAILED TO GET ROUTING TABLE" -ForegroundColor Red
}
}
finally
{
Remove-CimSession $session
}
}
}
if (!$TableOnly)
{
"`nCompleted in [{0}] milliseconds" -f $time.TotalMilliseconds
}
Write-Host "`n"
}
Get-RemoteRouteData -Subnet 192.168.1.205 -Credentials (Get-Credential)
I added the last line to run the function with a know IP Address (my domain controller). The result is this:
❯ import-module .\RoutingInfo.psm1 -force
PowerShell credential request
Enter your credentials.
User: scott.reeves@bluejacketsoftware.com
Password for user scott.reeves@bluejacketsoftware.com: ************
Scanning 192.168.1.205 for hosts...
Asking bjsdc01.bluejacketsoftware.com - 192.168.1.205 for it's Routing Table
Sanity Check...
scott.reeves@DELL17 C:\dev\WPA\PowerShell\RoutingInfo master ≣ +0 ~1 -1 ! [21:52]
❯
SOLVED:
The problem was because the $res variable was nested inside several layers of brackets, not the least of which was a for-eachobject. Since processing had not yet finished iterating over the entire list, the for-eachobject function wasn't capable of returning reasonable values, but rather internal representations. Adding the $res object to the $out collection, and finally printing the $out collection at the very end of the function returned useable results. For reference, here's the working code:
Function Get-RemoteRouteData{
[CmdletBinding()]
[OutputType([System.Management.Automation.PSCustomObject])]
param (
[Parameter(Mandatory = $true)]
[string]$Subnet,
[Parameter(Mandatory = $true)]
[object]$Credentials,
[Parameter(Mandatory = $false)]
[string]$Protocol = 'WSMan',
[Parameter(Mandatory = $false)]
[bool]$TableOnly,
[Parameter(Mandatory = $false)]
[string]$ErrorAct = 'SilentlyContinue'
)
if (!$TableOnly)
{
Write-Host "Scanning $subnet for hosts..."
}
#Use PSSubnetScan module for hosts
$computers = Get-PSSubnetScan -IPList $subnet -RevDNS -ICMPTest
$out = @() # Holds list of output objects
$time = Measure-Command {
foreach ($computer in $computers)
{
$name = $computer.RevDNS.Hostname
$ip = $computer.IPAddress.IPAddressToString
$ping = $computer.ICMP.IsActive
#Check to see if we have a host name or can ping. If neither, skip it.
if ((!$null -eq $name) -and (!$true -eq $ping))
{
Continue
}
if (!$TableOnly)
{
Write-Host "Asking $name - $ip for it's Routing Table"
}
$session = $null
try
{
#Use WMI Class directly
#([WMIClass]"\\$name\ROOT\CImv2:Win32_Process").Create("cmd.exe /c ipconfig /registerdns") | Out-Null
#([WMIClass]"\\192.168.1.205\ROOT\CImv2:Win32_Process").Create("cmd.exe /c winrm quickconfig"
#Use Cim Session
$option = New-CimSessionOption -Protocol $Protocol
$session = New-CimSession -ComputerName $name -Credential $Credentials -SessionOption $option -ErrorVariable $err;
$res = Get-NetRoute -CimSession $session
$out += $res
}
catch
{
if (!$TableOnly)
{
Write-Host "$ip - $name - FAILED TO GET ROUTING TABLE" -ForegroundColor Red
}
}
finally
{
if(!$null -eq $session){
Remove-CimSession $session
}
}
}
}
if (!$TableOnly)
{
"`nCompleted in [{0}] milliseconds" -f $time.TotalMilliseconds
}
Write-Host "`n"
$out
}
Get-RemoteRouteData -Subnet 192.168.1.0/24 -Credentials (Get-Credential)