Solved

PowerShell format-table with $Host.UI.RawUI.ForegroundColor issues

Posted on 2016-07-20
9
114 Views
Last Modified: 2016-07-21
Good morning,

I am having an issue colorizing within format-table using an expression and $Host.UI.RawUI.ForegroundColor.  I populated an array using garbage populated data and it works great:

$arrNetVirtLookupRecords = @()
100..150|%{
	$objNetVirtLookupRecord = $null
	$objNetVirtLookupRecord = New-Object PSObject -Property @{
		VMHost = $null;
		VSID = $null;
		VMName = $null;
		CustomerAddress = $null;
		ProviderAddress = $null;
		CustomerMAC = $null;
	}
	$objNetVirtLookupRecord.VMHost = If($_ % 2 -eq 0){"server101"} Else{"server102"}
	$objNetVirtLookupRecord.VSID = "1234567"
	$objNetVirtLookupRecord.VMName = "WINDOWS$_"
	$objNetVirtLookupRecord.CustomerAddress = "192.168.1.$_"
	$objNetVirtLookupRecord.ProviderAddress = "192.168.1.$_"
	$objNetVirtLookupRecord.CustomerMAC = "000000000$_"
	$arrNetVirtLookupRecords += $objNetVirtLookupRecord
}

$objOriginalColor = $Host.UI.RawUI.ForegroundColor
$arrNetVirtLookupRecords | Sort-Object VMHost, VMName | Format-Table @{
	Name="VMHost"
	Expression={
		If($_.VMHost -eq 'server102'){$Host.ui.rawui.ForegroundColor = "cyan"; $_.VMHost}
		Else{$Host.UI.RawUI.ForegroundColor = $objOriginalColor; $_.VMHost}
	}
}, VSID, VMName, CustomerAddress, ProviderAddress, CustomerMAC
$Host.UI.RawUI.ForegroundColor = $objOriginalColor

Open in new window


However when I run it against the real data it does not change the color.  When I run it against the real data and change the script to:

$objOriginalColor = $Host.UI.RawUI.ForegroundColor
$arrNetVirtLookupRecords | Sort-Object VMHost, VMName | Format-Table @{
	Name="VMHost"
	Expression={
		If("$($_.VMHost)" -eq 'server101'){$Host.ui.rawui.ForegroundColor = "cyan"; "Match)"}
		Else{$Host.UI.RawUI.ForegroundColor = $objOriginalColor; "No Match"}
	}
}, VSID, VMName, CustomerAddress, ProviderAddress, CustomerMAC
$Host.UI.RawUI.ForegroundColor = $objOriginalColor

Open in new window


Match and No Match are populated in the field appropriately but the color doesn't change.  Also if I print out the $Host.UI.RawUI.ForegroundColor in the expression it displays what the color should be, but the console doesn't display it.

Thanks for any assistance!
0
Comment
Question by:omnipower321
  • 4
  • 4
9 Comments
 
LVL 39

Expert Comment

by:footech
ID: 41721096
You're not running in the ISE are you?  That behaves different than a console.
0
 

Author Comment

by:omnipower321
ID: 41721099
I am not.  Straight up console.
0
 
LVL 39

Expert Comment

by:footech
ID: 41721543
I might have gotten somewhere with this.
What version of PS are you running?  Are you running everything on the same machine?

What I saw was with PS 5.0 that the color used was whatever the first object displayed used.  So if the first object was set to be cyan, then everything that followed was too.  With PS 4.0 the color changed according to the match.  I believe this is due to the change in PS 5.0 as to how Format-Table works.  If I changed the command to Format-List I observed the color change.

◦When you use the Format-Table command, table columns are now automatically formatted by evaluating the first 300ms of data that passes through the stream.
0
Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 

Author Comment

by:omnipower321
ID: 41721649
Thank you for the responses!  I am running these 2 tests from the same machine and am using PowerShell version 4.

I get the same behavior with Format-List:
$objOriginalColor = $Host.UI.RawUI.ForegroundColor
$arrNetVirtLookupRecords | Sort-Object VMHost, VMName | Format-List @{
	Name="VMHost"
	Expression={
		If("$($_.VMHost)" -eq 'server101'){$Host.ui.rawui.ForegroundColor = "cyan"; "$($_.VMHost) $($Host.UI.RawUI.ForegroundColor)"}
		Else{$Host.UI.RawUI.ForegroundColor = $objOriginalColor; "$($_.VMHost) $($Host.UI.RawUI.ForegroundColor)"}
	}
}, VSID, VMName, CustomerAddress, ProviderAddress, CustomerMAC
$Host.UI.RawUI.ForegroundColor = $objOriginalColor

Open in new window



VMHost          : server101 Cyan
VSID            : 1234567
VMName          : WINDOWS101
CustomerAddress : 192.168.1.x
ProviderAddress : 192.168.1.x
CustomerMAC     : 00000000101

VMHost          : server102 DarkYellow
VSID            : 1234567
VMName          : WINDOWS102
CustomerAddress : 192.168.1.x
ProviderAddress : 192.168.1.x
CustomerMAC     : 0000000000102

But the console color never changes.
0
 
LVL 83

Accepted Solution

by:
oBdA earned 300 total points
ID: 41721897
For the fun of it, here's a function. It expects an additional property '__Color' containing a hashtable with the fore- and/or background color the respective line should have (this hashtable will be splatted and used as argument for Write-Host).
-AutoSize and -HideTableHeaders are supported, and it works in the ISE as well.
Function Format-TableColored {
[CmdletBinding()]
Param(
	[Parameter(ValueFromPipeline=$true, Position=0)]
	[PSObject]$InputObject,
	[Switch]$AutoSize,
	[Switch]$HideTableHeaders,
	[String]$ColorProperty = "__Color"
)
	Begin {
		$Output = @()
		$Colors = @()
		$FirstValue = ''
		$StartColor = $False
		$ColorArgs = @{}
	}
	Process {
		If (!$FirstValue) {$FirstValue = [regex]::Escape(($InputObject.psobject.Properties | Select-Object -ExpandProperty Value -First 1))}
		$Colors += If ($InputObject.$ColorProperty -is [hashtable]) {$InputObject.$ColorProperty} Else {@{}}
		$Output += $InputObject | Select-Object -Property * -ExcludeProperty $ColorProperty
	}
	End {
		[void]$PSBoundParameters.Remove('ColorProperty')
		$PSBoundParameters['InputObject'] = $Output
		$i = 0
		(Format-Table @PSBoundParameters | Out-String) -split "`r`n" | ForEach-Object {
			If (!$StartColor -and ($_ -match "\s*$($FirstValue)")) {$StartColor = $True}
			If ($StartColor -and $_) {
				$ColorArgs = $Colors[$i++]
			} Else {
				$ColorArgs.Clear()
			}
			Write-Host -Object $_ @ColorArgs
		}
	}
}

Open in new window

Sample call:
Get-ChildItem C:\Windows\*.exe |
	Select-Object -Property `
		Name,
		Extension,
		LastWriteTime,
		@{Name='__Color'; Expression={
			Switch ($_.BaseName) {
				'Explorer'	{@{Fore='Black';Back='Yellow'}}
				'regedit'	{@{Back='Blue';Fore='White;}}
				'notepad'	{@{Back='DarkGray'}}
				'write'		{@{Fore='Magenta'}}
			}
		}} |
	Format-TableColored -AutoSize

Open in new window

In your case, this should work:
$arrNetVirtLookupRecords |
	Select-Object VMHost, VSID, VMName, CustomerAddress, ProviderAddress, CustomerMAC, @{Name='__Color'; Expression={If ($_.VMHost -eq 'server101') {@{Fore='Cyan'}}}} |
	Sort-Object VMHost, VMName | Format-TableColored

Open in new window

1
 
LVL 39

Assisted Solution

by:footech
footech earned 200 total points
ID: 41721921
Sorry, I can't think of any possible cause, unless there's a clue in the actual code you're running to gather data (but it seems unlikely).

One option which I found works with PS 5.0 (just using test data), is to specify the -GroupBy parameter of Format-Table.  However, if that that won't work for you, given what I found with PS 5.0, I'd pursue another route if I were you.  It doesn't seem to be a great idea to design something that will break when run on a new version of PS.
0
 
LVL 39

Expert Comment

by:footech
ID: 41722222
@oBdA - I like what you did with your function.  I was thinking about Format-Table > Out-String > Write-Host as an alternative but hadn't fleshed it out yet.
0
 

Author Comment

by:omnipower321
ID: 41722963
The function worked like a charm!  Thanks a bunch footech and oBdA.

I was going down a nasty path of Write-Hosts that was far less elegant.
0
 

Author Closing Comment

by:omnipower321
ID: 41722967
Thanks again for all of the help!
0

Featured Post

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
getting combo box selected item into variable 9 40
powershell query 2 23
DFS-R questions 4 23
Running powershell command to get-publicfolder and its hanging 1 24
Utilizing an array to gracefully append to a list of EmailAddresses
Are you one of those front-line IT Service Desk staff fielding calls, replying to emails, all-the-while working to resolve end-user technological nightmares? I am! That's why I have put together this brief overview of tools and techniques I use in o…
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question