I was preparing some auditing and reporting tools for some of newly received projects and wanted a way to formatting representation of data on my GUI form in nice way. To show this nice formatting you can use tags inside TextBlock and RichTextBox inside xaml code and binding can be used.These tags are as same as html tags. below examples are used on TextBlocks. For more on tagging you can check this link https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.documents.span, below are the few examples I used for formatting.
Sample text <Span FontWeight="Bold">bold</Span>, <Span FontStyle="Italic">italic</Span> and <Span TextDecorations="Underline">underlined</Span> words.
Text <Span Foreground="Blue">with blue </Span> <Span Foreground="Orange">and</Span> <Span Background="Magenta">Magenta highlight</Span>
Formatting text data on Richtextbox is very easy and formatting is done in same manner using tags on paragraphs in below format.
<Run FontFamily="Segoe UI" Text="This is "/>
<Run Foreground="#FFF00C0C" FontFamily="Segoe UI" Text="Line 1 "/>
<Run TextDecorations="Underline" FontStyle="Italic" FontFamily="Segoe UI" Text="Underline and Italic"/>
Download this script here, it is also available on github.com.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
<# .NOTES -------------------------------------------------------------------------------- Code generated using by: Visual Studio Created on: 26 June 2018 4:57 AM Get Help on: http://vcloud-lab.com Written by: Kunal Udapi Build & Tested on: Windows 10 Purpose: This script is an example of styling Font on textbox. -------------------------------------------------------------------------------- .DESCRIPTION GUI script generated using Visual Studio 2017 #> #Load required libraries Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase, System.Windows.Forms, System.Drawing [xml]$xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp9" Title="MainWindow" Height="315" Width="440"> <Grid> <TextBox Name='StrComputerName' HorizontalAlignment="Left" Height="23" Margin="180,11,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="151"/> <WrapPanel HorizontalAlignment="Left" Height="32" Margin="10,39,0,0" VerticalAlignment="Top" Width="401"> <TextBlock TextWrapping="Wrap" Text="ComputerName: " FontWeight="Bold" /> <TextBlock FontStyle='Italic' Text="{Binding Path=Text, ElementName=StrComputerName}"/> </WrapPanel> <TextBlock HorizontalAlignment="Left" Margin="10,71,0,0" VerticalAlignment="Top" Width="401" Height="28" > <!-- Label control with <Bold>bold</Bold>, <Italic>italic</Italic> and <Underline>underlined</Underline> text --> Sample text <Span FontWeight="Bold">bold</Span>, <Span FontStyle="Italic">italic</Span> and <Span TextDecorations="Underline">underlined</Span> words. </TextBlock> <TextBlock HorizontalAlignment="Left" Margin="10,99,0,0" VerticalAlignment="Top" Width="401" Height="33" xml:space="preserve"> Text <Span Foreground="Blue">with blue </Span> <Span Foreground="Orange">and</Span> <Span Background="Magenta">Magenta highlight</Span> <Span Foreground="Cyan">and Cyan color</Span> </TextBlock> <TextBlock HorizontalAlignment="Left" Height="53" Margin="10,132,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="401"> <TextBlock.Inlines> <Run FontWeight="Bold" FontSize="14" Text="Bold TextBox Example. " /> <Run FontStyle="Italic" Foreground="Red" Text="Red Text " /> <LineBreak/> <!-- Next Line --> <Run TextDecorations="StrikeThrough" Text="StrikeThrough " /> </TextBlock.Inlines> </TextBlock> <RichTextBox HorizontalAlignment="Left" Height="74" Margin="10,195,0,0" VerticalAlignment="Top" Width="401"> <FlowDocument> <Paragraph> <Run FontFamily="Segoe UI" Text="This is "/> <Run Foreground="#FFF00C0C" FontFamily="Segoe UI" Text="Line 1 "/> <Run TextDecorations="Underline" FontStyle="Italic" FontFamily="Segoe UI" Text="Underline and Italic"/> </Paragraph> <Paragraph> <Run FontFamily="Segoe UI" Text="This is "/> <Run Foreground="#FF3E8B8B" FontFamily="Segoe UI" Text="Line 2 "/> <Run Background="LightSkyBlue" FontFamily="Segoe UI" Text="Different Background"/> </Paragraph> </FlowDocument> </RichTextBox> </Grid> </Window> "@ #Read the form $Reader = (New-Object System.Xml.XmlNodeReader $xaml) $Form = [Windows.Markup.XamlReader]::Load($reader) #AutoFind all controls $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object { New-Variable -Name $_.Name -Value $Form.FindName($_.Name) -Force } #Mandetory last line of every script to load form [void]$Form.ShowDialog() |
The earlier shown tags example was to update XAML code directly, but I was also looking to update text after data collection, and my report should be looking nicer, cleaner and professional while sharing. As below I have 2 screenshots of same report but check the difference right side of screen definitely looks cool and much good in readable format, for example I need to highlight if there is a unwanted settings it should be shown as Red.
Here in this script I have created two functions, first is for TextBox and second is for RichTextBox. The gist is as below.
First function TextFormatting has below code and it is to format text on Textblock. More information on this object can be found here https://msdn.microsoft.com/en-us/library/system.windows.documents.run(v=vs.110).aspx.
$ObjRun = New-Object System.Windows.Documents.Run
$ObjRun.FontWeight = 'Bold'
$ObjRun.Text = 'Your text'
$TextBlock.Inlines.Add($ObjRun)
Next function Format-RichTextBox formats text on richtextbox, more Information can be found on this .net object as below urls.
https://msdn.microsoft.com/en-us/library/system.windows.documents.textrange(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.documents.textrange.applypropertyvalue(v=vs.110).aspx
$RichTextRange = New-Object System.Windows.Documents.TextRange($RichTextBoxControl.Document.ContentEnd, $RichTextBoxControl.Document.ContentEnd) #($RichTextBoxControl.Document.ContentStart, $RichTextBoxControl.Document.ContentEnd)
$RichTextRange.Text = 'YourText'
$RichTextRange.ApplyPropertyValue([System.Windows.Documents.TextElement]::BackgroundProperty, 'DarkGreen')
Download this script here, it is also available on github.com.
<#
.NOTES
--------------------------------------------------------------------------------
Code generated using by: Visual Studio 2017
Created on: 26 June 2018 4:57 AM
Get Help on: http://vcloud-lab.com
Written by: Kunal Udapi
Build & Tested on: Windows 10
Purpose: This script is an example of styling Font on textbox.
Useful Article: http://www.wpf-tutorial.com/basic-controls/the-textblock-control-inline-formatting/
--------------------------------------------------------------------------------
.DESCRIPTION
GUI script generated using Visual Studio 2017
#>
$Path = Split-Path -Parent $MyInvocation.MyCommand.Path
$ImgSrc = "$Path\BackGround.jpg"
#Load required libraries
Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase, System.Windows.Forms, System.Drawing
[xml]$xaml = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp10"
Title="Server Audit" Height="390" Width="476" ResizeMode="NoResize" Topmost="True" WindowStartupLocation="CenterScreen">
<Grid>
<Image HorizontalAlignment="Left" Height="419" VerticalAlignment="Top" Width="469" Source="$ImgSrc"/>
<Label Name='Url' Content='http://vcloud-lab.com' HorizontalAlignment="Left" Margin="334,7,0,0" VerticalAlignment="Top" Foreground="LightGray" Cursor='Hand' ToolTip='http://vcloud-lab.com'/>
<TextBox Name='ComputerName' HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="$env:COMPUTERNAME" VerticalAlignment="Top" Width="177"/>
<Button Name='Audit' Content="Audit" HorizontalAlignment="Left" Margin="192,10,0,0" VerticalAlignment="Top" Height="23" Width="75"/>
<TextBlock Name='CompInfo' HorizontalAlignment="Left" Margin="10,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="449" Height="180"/>
<RichTextBox Name='AuditPart' HorizontalAlignment="Left" Height="110" Margin="10,230,0,0" VerticalAlignment="Top" Width="440">
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0" />
</Style>
</RichTextBox.Resources>
<FlowDocument>
<Paragraph>
<!-- <Run Text="RichTextBox"/> -->
</Paragraph>
</FlowDocument>
</RichTextBox>
</Grid>
</Window>
"@
#Read the form
$Reader = (New-Object System.Xml.XmlNodeReader $xaml)
$Form = [Windows.Markup.XamlReader]::Load($reader)
#AutoFind all controls
$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object {
New-Variable -Name $_.Name -Value $Form.FindName($_.Name) -Force
}
$AuditPart.IsReadOnly = $true
$Url.Add_MouseLeftButtonUp({[system.Diagnostics.Process]::start('http://www.google.com')})
$Url.Add_MouseEnter({$Url.Foreground = 'DarkGray'})
$Url.Add_MouseLeave({$Url.Foreground = 'LightGray'})
function TextFormatting {
[CmdletBinding(
ConfirmImpact='Medium',
HelpURI='http://vcloud-lab.com'
)]
Param (
[parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[String]$Text,
[Switch]$Bold, #https://docs.microsoft.com/en-us/uwp/api/windows.ui.text.fontweights
[Switch]$Italic, #https://docs.microsoft.com/en-us/uwp/api/windows.ui.text.fontstyle
[String]$TextDecorations, #https://docs.microsoft.com/en-us/uwp/api/windows.ui.text.textdecorations
[Int]$FontSize,
[String]$Foreground,
[String]$Background,
[Switch]$NewLine
)
Begin {
#https://docs.microsoft.com/en-us/uwp/api/windows.ui.text
$ObjRun = New-Object System.Windows.Documents.Run
function TextUIElement {
Param (
[parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[String]$PropertyName
)
$Script:PropValue = $PropertyName
Switch ($PropertyName) {
'Bold' {'FontWeight'} #Thin, SemiLight, SemiBold, Normal, Medium, Light, ExtraLight, ExtraBold, ExtraBlack, Bold, Black
'Italic' {'FontStyle'} #Italic, Normal, Oblique
'TextDecorations' {'TextDecorations'} #None, Strikethrough, Underline
'FontSize' {'FontSize'}
'Foreground' {'Foreground'}
'Background' {'Background'}
'NewLine' {'NewLine'}
}
}
}
Process {
if ($PSBoundParameters.ContainsKey('NewLine')) {
$ObjRun.Text = "`n$Text "
}
else {
$ObjRun.Text = $Text
}
$AllParameters = $PSBoundParameters.Keys | Where-Object {$_ -ne 'Text'}
foreach ($SelectedParam in $AllParameters) {
$Prop = TextUIElement -PropertyName $SelectedParam
if ($PSBoundParameters[$SelectedParam] -eq [System.Management.Automation.SwitchParameter]::Present) {
$ObjRun.$Prop = $PropValue
}
else {
$ObjRun.$Prop = $PSBoundParameters[$Prop]
}
}
$ObjRun
}
}
function Format-RichTextBox {
#https://msdn.microsoft.com/en-us/library/system.windows.documents.textelement(v=vs.110).aspx#Propertiesshut
param (
[parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[System.Windows.Controls.RichTextBox]$RichTextBoxControl,
[String]$Text,
[String]$ForeGroundColor = 'Black',
[String]$BackGroundColor = 'White',
[String]$FontSize = '12',
[String]$FontStyle = 'Normal',
[String]$FontWeight = 'Normal',
[Switch]$NewLine
)
$ParamOptions = $PSBoundParameters
$RichTextRange = New-Object System.Windows.Documents.TextRange(<#$RichTextBoxControl.Document.ContentStart#>$RichTextBoxControl.Document.ContentEnd, $RichTextBoxControl.Document.ContentEnd)
if ($ParamOptions.ContainsKey('NewLine')) {
$RichTextRange.Text = "`n$Text"
}
else {
$RichTextRange.Text = $Text
}
$Defaults = @{ForeGroundColor='Black';BackGroundColor='White';FontSize='12'; FontStyle='Normal'; FontWeight='Normal'}
foreach ($Key in $Defaults.Keys) {
if ($ParamOptions.Keys -notcontains $Key) {
$ParamOptions.Add($Key, $Defaults[$Key])
}
}
$AllParameters = $ParamOptions.Keys | Where-Object {@('RichTextBoxControl','Text','NewLine') -notcontains $_}
foreach ($SelectedParam in $AllParameters) {
if ($SelectedParam -eq 'ForeGroundColor') {$TextElement = [System.Windows.Documents.TextElement]::ForegroundProperty}
elseif ($SelectedParam -eq 'BackGroundColor') {$TextElement = [System.Windows.Documents.TextElement]::BackgroundProperty}
elseif ($SelectedParam -eq 'FontSize') {$TextElement = [System.Windows.Documents.TextElement]::FontSizeProperty}
elseif ($SelectedParam -eq 'FontStyle') {$TextElement = [System.Windows.Documents.TextElement]::FontStyleProperty}
elseif ($SelectedParam -eq 'FontWeight') {$TextElement = [System.Windows.Documents.TextElement]::FontWeightProperty}
$RichTextRange.ApplyPropertyValue($TextElement, $ParamOptions[$SelectedParam])
}
}
$Audit.Add_Click({
$CompInfo.Text = ''
$AuditPart.SelectAll()
$AuditPart.Selection.Text = ''
$OS = Get-WmiObject win32_OperatingSystem -ComputerName $ComputerName.Text
$Bios = Get-WmiObject win32_Bios -ComputerName $ComputerName.Text
$ComSys = Get-WmiObject win32_ComputerSystem -ComputerName $ComputerName.Text
$Patch = Get-HotFix -ComputerName $ComputerName.Text | Sort-Object -Property InstalledOn -Descending | Select-Object HotFixID, InstalledOn -First 1
$TimeZone = Get-WmiObject -Class win32_timezone -ComputerName $ComputerName.Text
#$CompInfo.Inlines.Add($(TextFormatting -Text 'OS Name: ' -Bold -FontSize 14 -Italic -TextDecorations Underline -Foreground DarkGreen -Background DarkRed))
$CompInfo.Inlines.Add($(TextFormatting -Text 'OS Name: ' -Bold -Italic))
$CompInfo.Inlines.Add("$($OS.Caption) `n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'OS Version: ' -Bold))
$CompInfo.Inlines.Add("$($OS.Version) `n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'OS Architecture: ' -Bold))
$CompInfo.Inlines.Add("$($OS.OSArchitecture) `n`n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'Hardware Manufacturer: ' -Bold -FontSize 16))
$CompInfo.Inlines.Add("$($ComSys.Manufacturer) `n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'Hardware Model: ' -Bold))
$CompInfo.Inlines.Add("$($ComSys.Model) `n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'Sr. Number: ' -Bold))
$CompInfo.Inlines.Add("$($Bios.SerialNumber) `n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'Bios Version: ' -Bold))
$CompInfo.Inlines.Add("$($Bios.Name) `n`n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'Last patch and installed date: ' -Bold))
$CompInfo.Inlines.Add($(TextFormatting -Text $Patch.HotFixID -Italic -TextDecorations Underline -Foreground Blue -Bold))
$CompInfo.Inlines.Add(" - $($Patch.InstalledOn) `n")
$CompInfo.Inlines.Add($(TextFormatting -Text 'System TimeZone: ' -Bold))
if ($TimeZone.StandardName -eq 'India Standard Time') {
$CompInfo.Inlines.Add($(TextFormatting -Text $TimeZone.StandardName -Italic -Background DarkRed -Foreground White))
}
else {
$CompInfo.Inlines.Add($(TextFormatting -Text $TimeZone.StandardName -Italic -Foreground DarkGreen))
}
$CompInfo.Inlines.Add(' - Should be EST, CST or PST')
$CPU = Get-WmiObject win32_Processor -ComputerName $ComputerName.Text
$Service = Get-Service -Name WinRM, RemoteRegistry -ComputerName $ComputerName.Text
Format-RichTextBox -RichTextBoxControl $AuditPart -Text 'Processor: ' -FontWeight Bold -FontSize 18
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $CPU.Name
Format-RichTextBox -RichTextBoxControl $AuditPart -Text 'Virtualization Enabled: ' -FontWeight Bold -NewLine
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $CPU.VirtualizationFirmwareEnabled
$AuditPart.AppendText("`n")
Format-RichTextBox -RichTextBoxControl $AuditPart -Text 'Windows Remoting Service: ' -FontWeight Bold -NewLine
$Winrm = $Service | Where-Object {$_.Name -eq 'WinRM'}
if ($Winrm.Status -eq 'Running') {
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $Winrm.Status -BackGroundColor LightGreen
}
elseif ($Winrm.Status -eq 'Stopped') {
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $Winrm.Status -BackGroundColor DarkRed -ForeGroundColor White
}
else {
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $Winrm.Status -BackGroundColor Yellow
}
Format-RichTextBox -RichTextBoxControl $AuditPart -Text ' - WinRM must be Running'
$RemoteRegistry = $Service | Where-Object {$_.Name -eq 'RemoteRegistry'}
Format-RichTextBox -RichTextBoxControl $AuditPart -Text 'Remote Registry Service: ' -FontWeight Bold -NewLine
if ($RemoteRegistry.Status -eq 'Running') {
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $RemoteRegistry.Status -BackGroundColor DarkRed -ForeGroundColor White
}
else {
Format-RichTextBox -RichTextBoxControl $AuditPart -Text $RemoteRegistry.Status -BackGroundColor LightGreen
}
Format-RichTextBox -RichTextBoxControl $AuditPart -Text ' - Remove Registry must be stopped'
<#
$AuditPart.AppendText("New Text`n")
$AuditPart.Selection.Select($AuditPart.Selection.Start,$AuditPart.Selection.End)
$AuditPart.Selection.ApplyPropertyValue([System.Windows.Documents.TextElement]::ForegroundProperty,[System.Windows.Media.Brushes]::Red)
$AuditPart.AppendText("2nd Text`r")
$AuditPart.ScrollToEnd()
#>
})
#Mandetory last line of every script to load form
[void]$Form.ShowDialog()
Useful Articles
Powershell GUI encode decode images
Powershell WPF Charts dashboard demo
Part 1: Create WPF XAML powershell GUI form with Visual studio
Part 2: Powershell and WPF: Build GUI applications tutorial
Part 3: Create shorter Microsoft Powershell WPF automated clean script
Powershell PoshGUI: Convert user to SID and vice versa using
Microsoft Powershell GUI: Change Internet Options connections Lan settings proxy server grayed out