Author Posts

December 3, 2013 at 12:16 pm

I'm currently working on a script that will query a list of computers and record the monitor information.

Simple enough one would think and, for you experts, it probably is. For me, however, I am having a hard time grasping the formatting of the output when the script finds a computer that has two monitors connected.

$$monitor = gwmi WmiMonitorID -Namespace root\wmi | select pscomputername,ManufacturerName,UserFriendlyName,SerialNumberID
$Mfgr=($monitor.ManufacturerName | foreach {[char]$_}) -join ""
$Model=($monitor.UserFriendlyName | foreach {[char]$_}) -join ""
$Ser=($monitor.SerialNumberID | foreach {[char]$_}) -join ""
$cname=($monitor.PSComputerName | foreach {($_.Split('='))[0]}) -Join ","
#just to see what the output is
write-host $cname,$mfgr,$model,$ser

Output from this script does show information for two connected monitors, and does so on one line, but the formatting of the fields that contain information for more than one monitor is "off", in that there is a large gap between values.

Example:

$mfgr shows SAMDEL and I want it to show as SAM,DEL

There is a space 13 characters wide between SAM and DEL that the post will not reproduce

Same thing with the Model Number, as well as Serial Number

I've tried doing a replace, similar to the following:

$mfgr=($mfgr -replace '             ',',')  

but the result is still SAM DEL

It's like the replace doesn't "see" the large gap.

I've read about formatting on multiple sites, but I cannot seem to grasp this particular concept.

Could someone explain it to me and maybe show me why my replace statement didn't find the large empty gap between the mfgr?

December 3, 2013 at 12:24 pm

Ah. Yeah, that's a bit tricky. And different versions of PowerShell will "do some of this for you" which makes it harder to see what's going wrong.

$monitor will contain two complete objects if the computer has more than one monitor. That's where you're going wrong on this. This:

$Mfgr=($monitor.ManufacturerName | foreach {[char]$_}) -join ""

If $monitor contains two things, then $monitor.manufacturername doesn't technically work. Now, in PowerShell v3, it'll implicitly enumerate the collection and spit out the two strings from each object's ManufacturerName – that's the under-the-hood magic that makes this hard to figure out. So in v3 or later:

$Mfgr=($monitor.ManufacturerName | foreach {[char]$_}) -join ","

Ought to get you closer. But I guess more traditionally someone would do:

$Mfgr = @()
ForEach ($one_monitor in $monitor) {
 $mfgr += $one_monitor.manufacturername
}
$all_mfgr = $mfgr -join ","

So, create an empty array for names, populate the names from each monitor, and then join them into a comma-separated list. Whether you do it exactly like that or not doesn't matter, but I think the logic is a bit easier to follow that way. You could obviously do your model, serial number, and other items the same way, and populate them all in the same ForEach loop. That'd perform better than what you're doing now.

$Mfgr = @()
$Model = @()
ForEach ($one_monitor in $monitor) {
 $mfgr += $one_monitor.manufacturername
 $model += $one_monitor.userfriendlyname
}
$all_mfgr = $mfgr -join ","
$all_model = $model -join ","

Only one loop, that way, instead of the four you've got.