I then changed the line so that the command was assigned to a variable, so that I could test the validity of the variable before displaying it in the console window:
When I run the code in the PowerShell ISE, the output is correctly displayed on multiple lines. However when I run the code in a PowerShell console, it displays like this:
Well to be fair you don’t show how you retrieve the variable value. You could be sticking it in a form for all we know. It was a good guess as it does look like it was forced into a single string. Please share how you are outputting the stored variable.
I paused the script again at the same point (using a breakpoint), and checked the value of the variable $x from the ISE command line:
[DBG]: PS C:\Users\Julian\Documents\WindowsPowerShell\Scripts> $x
Address Port Type
------- ---- ----
172.20.80.80 3260 Static
172.20.80.81 3260 Static
As you can see, the output from the script does NOT match the variable value???
The variable is an object, obviously, so what’s going on here?
I don’t understand why the script runs and each iteration of the loop produces a different output.
Looks like Output-Object correctly outputs the object $x as its value is formatted, and by assigning it to a string variable, I can ouput the variable, using Write-Host, in colour!
Note:
$x is type System.Array
$Output is type System.String
What method of outputting $x would you use? You can’t just put $x on a line by itself within the script as that is not recognised as the name of any cmdlets. It has to be output using a PowerShell method.
That is incorrect. But the question is too vague. If I really just wanted it to output it’s default just like the first command, then yes, just drop $x and let powershells implicit output handle it or don’t store it in a variable at all.
Run each of these independently. Note that even though $x isn’t surrounded by quotes in the 4th example, Write-Host always converts the input to string.
# The following 2 examples will have the same "object" output dictated by its own default formatting rules
foreach($esx in $esxhosts){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "=========================================="
Write-Host "iSCSI Targets on $esx"
Write-Host "=========================================="
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
}
}
foreach($esx in $esxhosts){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "=========================================="
Write-Host "iSCSI Targets on $esx"
Write-Host "=========================================="
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
$x = Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
$x
}
}
# these two will be the same incorrectly stringigified versions
foreach($esx in $esxhosts){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "=========================================="
Write-Host "iSCSI Targets on $esx"
Write-Host "=========================================="
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
$x = Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
"$x"
}
}
foreach($esx in $esxhosts){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "=========================================="
Write-Host "iSCSI Targets on $esx"
Write-Host "=========================================="
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
$x = Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
Write-Host $x
}
}
What you’re seeing in the first example is the default member (property) set. It’s output nice for your eyes by the powershell formatting system based on the cmdlets own format specification. Now a lot of cmdlets will make the ToString() method actually output the same or something just as nice for human consumption. However some, like this IscsiHBA cmdlet, doesn’t offer anything special for ToString() so powershell gets garbage when it asks it to “stringify” itself.
Now for what you see on the screen, if you want to capture the text exactly like that and don’t care about object, just Out-String it. Check these examples.
# Get-Member on the default, easy on the eyes output.
foreach($esx in $esxhosts | Select-Object -First 1){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "=========================================="
Write-Host "iSCSI Targets on $esx"
Write-Host "=========================================="
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
$x = Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
$x # implicit output so you can see it's formatted the way you like
$x | Get-Member
}
}
# Now we'll show the same output but this time it's been turned into pretty, but hard to work with down the pipeline, string
foreach($esx in $esxhosts | Select-Object -First 1){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "=========================================="
Write-Host "iSCSI Targets on $esx"
Write-Host "=========================================="
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
$x = Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
$x | Out-String
$x | Out-String | Get-Member
}
}
So even though both show the same output on the screen, one is still an object and the other is not. Now if someone made the cmdlet’s ToString() method do that, it’d be a lot easier to use in double quotes or Write-Host.
So it really comes down to what you are trying to do with the output. Are you wanting to both show it to use and capture the object? Perhaps just do both, because the -Host cmdlets aren’t sent on stdout so it won’t be captured (without trying hard to do so) while the object does, try it yourself!
# Pretty output for the eys and only the objects are collected in $result.
$result = foreach($esx in $esxhosts){
$hba = $esx | Get-VMHostHba -Type iScsi
if ($hba){
Write-Host "==========================================" -ForegroundColor DarkCyan
Write-Host "iSCSI Targets on $esx" -ForegroundColor Gray
Write-Host "==========================================" -ForegroundColor DarkCyan
# Get-IScsiHbaTarget -IScsiHba $hba -Type Send | Sort Address
$x = Get-IScsiHbaTarget -IScsiHba $hba | Sort Address
Write-Host ($x | Out-String) -ForegroundColor Cyan
$x
}
}