Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Monday, December 12, 2016 12:03 AM
Hello,
I'm a fairly new user to powershell and seem to be stuck.
I am trying to format a field of "Select-Object" data but can seem to work out how:
$os | select @{Name = "Status";Expression = {$Status}},
@{Name = "Mem%Free"; Expression = {$pctFree}},
@{Name = "FreeMem(GB)";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalMem(GB)";Expression = {[math]::Round($_.TotalVisibleMemorySize/1mb)}}
Essentially I am trying to format $Status one of three colors. Red for $Status "Critical", Yellow for $Status "Warning", and "Green" for $Status . $Status is determined by a previous If statement.
I've been trying to accomplish this by piping the above data through various things such as write-host, string-out etc. I feel I'm going about this wrong. My core goal of data output has been achieved, but this one visual indicator I am trying to implement is driving me nuts!
Currently my script produces the following un-formatted:
Status Mem%Free FreeMem(GB) TotalMem(GB)
OK 53.17 3.95 7
Thanks so much!
All replies (12)
Monday, December 12, 2016 8:22 PM ✅Answered | 1 vote
Here is a hint as to how to do this without so much extra code.
function test-output{
Write-Host ('{0,-10}{1,-20}{2,-20}{3,-20}' -f 'Status', 'Mem%Free', 'FreeMem(GB)', 'TotalMem(GB)') -fore yellow
Get-WmiObject Win32_OperatingSystem |
ForEach-Object{
$color = if($_.Status -eq 'Ok'){'green'}else{'red'}
$line = "{0,-10}{1,-20:N2}{2,-20:N2}{3,-20:N2}" -f $_.Status,(100 * $_.FreePhysicalMemory/$_.TotalVisibleMemorySize),($_.FreePhysicalMemory/1mb),
($_.TotalVisibleMemorySize/1mb)
Write-Host $line -fore $color
}
}
test-output
No idea where you are getting $stat and $freepct from. Restart PowerShell and run that statement again and you will see what I am saying.
\(ツ)_/
Monday, December 12, 2016 1:22 AM | 1 vote
Powershell is not made for being colorful by default. Select-Object is not able to produce colored Output. So if you really need this, you would have to make it a kind of by yourself. You would have to parse the output and colorize it with Write-Host "something" -ForegroundColor Red or Green or Yelow or .... but in my opinion it's not worth it and it breaks the pipeline. So it really has to be the last step in your pipeline.
You also could create an HTML report and colorize this. There are several ways to do this. Here you can learn some: Creating HTML Reports in Powershell.
For me most of the time it's enough to sort the output by status. Or if you want to have it a little more manager compatible you can use Out-GridView.
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join''
Monday, December 12, 2016 1:26 AM
The single most important thing here is that you need to learn PowerShell. You cannot do this by guessing and posting really lame guesses and begging for help. It just won't work.
\(ツ)_/
Monday, December 12, 2016 7:02 AM
Agreed,
Creating a HTML Report does seem like the best way to achieve this!
Monday, December 12, 2016 4:14 PM
The single most important thing here is that you need to learn PowerShell. You cannot do this by guessing and posting really lame guesses and begging for help. It just won't work.
\(ツ)_/
Again, my script works. Simply was looking for a cosmetic improvement at this point.
Monday, December 12, 2016 4:16 PM
Powershell is not made for being colorful by default. Select-Object is not able to produce colored Output. So if you really need this, you would have to make it a kind of by yourself. You would have to parse the output and colorize it with Write-Host "something" -ForegroundColor Red or Green or Yelow or .... but in my opinion it's not worth it and it breaks the pipeline. So it really has to be the last step in your pipeline.
You also could create an HTML report and colorize this. There are several ways to do this. Here you can learn some: Creating HTML Reports in Powershell.
For me most of the time it's enough to sort the output by status. Or if you want to have it a little more manager compatible you can use Out-GridView.
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join''
I've done a lot of looking on the topic. I think the easiest, most comprehensible way to achieve this is indeed converting the output to HTML.
Monday, December 12, 2016 7:50 PM
$os | select <yourOwnCodeMindingThePropertiesNames> | %{
write-host ' status free% free(GB) total(GB)' -fore darkyellow
}{
$s=$_.status
write-host ('{0,10}' -f $s) -back (if($s -eq 'OK'){'green'}elseif($s -eq 'Warning'){'yellow'}else{'red'}) -nonew
write-host (' {0,10} {1,10} {2,10}' -f $_.${free%},$_.${free(GB)},$_.${total(GB)})
}
Simple.
▪
Hmmm not quite:
$pc = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
$pc | select @{Name = "Status";Expression = {$Stat}},
@{Name = "Mem%Free"; Expression = {$Freepct}},
@{Name = "FreeMem(GB)";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalMem(GB)";Expression = {[math]::Round($_.TotalVisibleMemorySize/1mb)}}| %{
write-host ' Status Mem%Free FreeMem(GB) TotalMem(GB)' -fore darkyellow
}{
$s=$_.status
write-host ('{0,10}' -f $s) -back (if($s -eq 'OK'){'green'}elseif($s -eq 'Warning'){'yellow'}else{'red'}) -nonew
write-host (' {0,10} {1,10} {2,10}' -f $_.${Mem%Free},$_.${FreeMem(GB)},$_.${TotalMem(GB)})
Doesn't appear to like that If statement:
PS Microsoft.PowerShell.Core\FileSystem::\\shcsd\sharp\soc\Users\dobth\My Documents\WindowsPowerShell> Get-MemoryUsage -ComputerName IS1607747
Status Mem%Free FreeMem(GB) TotalMem(GB)
if : The term 'if' is not recognized as the name of a cmdlet, function, script file, or operable program. Check
the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:25 char:49
+ write-host ('{0,10}' -f $s) -back (if($s -eq 'OK'){'gree ...
+ ~~
+ CategoryInfo : ObjectNotFound: (if:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Monday, December 12, 2016 7:56 PM
You cannot mix Write-Host statements into a computed select-object statement. I t will not work in any kind of meaningful way.
Your computed statement is also badly broken. Start by getting the computed statement to work correctly before attempting to add color.
\(ツ)_/
Monday, December 12, 2016 8:02 PM
You cannot mix Write-Host statements into a computed select-object statement. I t will not work in any kind of meaningful way.
Your computed statement is also badly broken. Start by getting the computed statement to work correctly before attempting to add color.
\(ツ)_/
Could you elaborate?
$pc = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
$pc | select @{Name = "Status";Expression = {$Stat}},
@{Name = "Mem%Free"; Expression = {$Freepct}},
@{Name = "FreeMem(GB)";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalMem(GB)";Expression = {[math]::Round($_.TotalVisibleMemorySize/1mb)}}
Yields the expected output:
Status Mem%Free FreeMem(GB) TotalMem(GB)
OK 47.05 3.49 7
Tuesday, December 13, 2016 12:06 AM
Thank you jrv. Excellent uses of ForEach-Object and formatting operator. Thanks for your assistance and example!
Here is the final function:
Function Get-MemoryUsage {
[cmdletbinding()]
Param($ComputerName)
$pc = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
$Freepct = [math]::Round(($pc.FreePhysicalMemory/$pc.TotalVisibleMemorySize)*100,2)
if ($Freepct -ge 45) {
$Stat = "OK"
}
elseif ($Freepct -ge 15 ) {
$Stat = "Warning"
}
else {
$Stat = "Critical"
}
Write-Host ('{0,-10}{1,-10}{2,-15}{3,-10}' -f "`nStatus", 'Mem%Free', 'FreeMem(GB)', 'TotalMem(GB)')
Write-Host ('{0,-10}{1,-10}{2,-15}{3,-10}' -f '', '', '', '')
$pc | ForEach-Object{
$color = if($Stat -eq 'Ok'){'green'}elseif($Stat -eq 'Warning'){'Yellow'}else{'red'}
$line = "{0,-10}{1,-10:N2}{2,-15:N2}{3,-10:N2}" -f $Stat,(100 * $_.FreePhysicalMemory/$_.TotalVisibleMemorySize),($_.FreePhysicalMemory/1mb),
($_.TotalVisibleMemorySize/1mb)
Write-Host $line -fore $color
If ($color -eq 'red') {
Write-Host "`nInsufficent Ram" -fore $color
}
else {
Write-Host "`nMemory Check - OK" -fore $color
}
}
}
The resulting output:
and again called as a function called in larger module:
Kudos JRV. Much appreciated!
Tuesday, December 13, 2016 12:16 AM
Could be greatly simplified but it works so you are set - I guess.
Have fun.
\(ツ)_/
Tuesday, December 13, 2016 12:36 AM
I'll keep trying to "simplify" it in mind; I imagine it will come with time and emphasis on best practice.
Only been at this about a week or so.