In this article I am showing some different ProgressBars for WPF GUI, This progressbar can show your chunk of silhouette image loading instead progress nicely. Below is the demo for my new progressbars, It can be used as an animated text or image. Images should be silhouette, A silhouette is the image of a person, animal, object or scene represented as a solid shape of a single color, usually black, with its edges matching the outline of the subject. The interior of a silhouette is featureless, and the whole is typically presented on a light background, usually white, or none at all.

As start, I need image first and created my own text silhouette image using Microsoft PowerPoint.

In the PowerPoint Add a Text Box from shapes. Change Text color to black, do not keep any margin for text in the box, it should be as tight as possible, Choose your favorite font and size. Box background fill should be none Select outline of textbox to none Type your text Right click text box and from context menu choose Save as Picture. Save it as png extension This is critical step, (Need only Png, as this file formats can retain background transparency). View and Verify your file in photo viewer, It looks good to me, using above method I created few more images.

I have created xaml gui form using Visual Studio, Added ProgressBar, TextBlock and Button controls to it, There is little change I made to the ProgressBar as shown below.

<ProgressBar Name="ProgressBar1" HorizontalAlignment="Left" Height="41" VerticalAlignment="Top" Width="264" Margin="10,10,0,0" Background="{x:Null}">

<ProgressBar.OpacityMask>

<ImageBrush ImageSource="C:\Temp\Completed.png"/>

</ProgressBar.OpacityMask>

</ProgressBar>

Settings on ProgressBar background (color) is set to null or the color you want, unclosed it in the last, Added ProcessBar.OpacityMask property with ImageSource as earlier created png file and in the last close ProgressBar property.

As to show progressbar correctly on wpf powershell, I am using runspaces in the script. This url link by Travor Jones has nice guide to understand powershell runspace correctly.Without runspaces my script will hung and unresponsive, Doesn't show animatation progress and freezes, directly shows 100% progress once all processing done. Here is in below video I used picture as progressbar. When using images make sure you correctly provide complete locations in the script.

Download this complete project 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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 #Load Libraries Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase, System.Windows.Forms, System.Drawing $Runspace = [runspacefactory] :: CreateRunspace() $Runspace .ApartmentState = "STA" $Runspace .ThreadOptions = "ReuseThread" $Runspace .Open() $code = { #Build the GUI [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:WpfApp6" Title="ProgressBar Demo" Height="220" Width="500" Topmost="True"> <Grid> <ProgressBar Name="ProgressBar1" HorizontalAlignment="Left" Height="41" VerticalAlignment="Top" Width="264" Margin="10,10,0,0" Background="{x:Null}"> <ProgressBar.OpacityMask> <ImageBrush ImageSource="C:\Temp\Processbar\Images\Processing.png"/> </ProgressBar.OpacityMask> </ProgressBar> <TextBlock Name="TextBlock1" HorizontalAlignment="Left" Margin="281,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> <Button Name="Button1" Content="Complete" HorizontalAlignment="Left" Margin="279,31,0,0" VerticalAlignment="Top" Width="75"/> <ProgressBar Name="ProgressBar2" HorizontalAlignment="Left" Height="41" VerticalAlignment="Top" Width="264" Margin="10,56,0,0"> <ProgressBar.OpacityMask> <ImageBrush ImageSource="C:\Temp\Processbar\Images\Completed.png"/> </ProgressBar.OpacityMask> </ProgressBar> <TextBlock Name="TextBlock2" HorizontalAlignment="Left" Margin="279,56,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="128"/> <Button Name="Button2" Content="Complete" HorizontalAlignment="Left" Margin="279,72,0,0" VerticalAlignment="Top" Width="75"/> <ProgressBar Name="ProgressBar3" HorizontalAlignment="Left" Height="41" VerticalAlignment="Top" Width="203" Margin="10,102,0,0" > <ProgressBar.OpacityMask> <ImageBrush ImageSource="C:\Temp\Processbar\Images\Loading.png"/> </ProgressBar.OpacityMask> </ProgressBar> <TextBlock Name="TextBlock3" HorizontalAlignment="Left" Margin="218,102,0,0" TextWrapping="Wrap" Text="Loading" VerticalAlignment="Top" Width="189"/> <Button Name="Button3" Content="Load" HorizontalAlignment="Left" Margin="218,123,0,0" VerticalAlignment="Top" Width="75"/> </Grid> </Window> "@ $syncHash = [hashtable] :: Synchronized( @ {}) $reader =( New-Object System.Xml.XmlNodeReader $xaml ) $syncHash .Window=[Windows.Markup.XamlReader] :: Load( $reader ) function Update-Progress { param( $syncHash , $ProgressNumber , $TargetBox ) $syncHash .Host = $host $Runspace = [runspacefactory] :: CreateRunspace() $Runspace .ApartmentState = "STA" $Runspace .ThreadOptions = "ReuseThread" $Runspace .Open() $Runspace .SessionStateProxy.SetVariable( "syncHash" , $syncHash ) $Runspace .SessionStateProxy.SetVariable( "ProgressNumber" , $ProgressNumber ) #$Runspace.SessionStateProxy.SetVariable("TargetBox",$TargetBox) $code = { $syncHash .Window.Dispatcher.invoke( [action]{ $syncHash .Button1.isEnabled = $false $syncHash .Button2.isEnabled = $false $syncHash .Button3.isEnabled = $false } ) if ( $ProgressNumber -eq 1) { for ( $i =0 ; $i -lt 101 ; $i ++) { $syncHash .Window.Dispatcher.invoke( [action]{ $syncHash .ProgressBar1.Value = $i $syncHash .TextBlock1.Text = "Working On Comp$i" } ) Start-Sleep -Milliseconds 100 } } elseif ( $ProgressNumber -eq 2) { for ( $i =0 ; $i -lt 101 ; $i ++) { $syncHash .Window.Dispatcher.invoke( [action]{ $syncHash .ProgressBar2.Value = $i $syncHash .TextBlock2.Text = "Process created $i" } ) Start-Sleep -Milliseconds 100 } } elseif ( $ProgressNumber -eq 3) { for ( $i =0 ; $i -lt 101 ; $i ++) { $syncHash .Window.Dispatcher.invoke( [action]{ $syncHash .ProgressBar3.IsIndeterminate = $True $syncHash .TextBlock3.Text = "Loading... File$i" } ) Start-Sleep -Milliseconds 100 } } $syncHash .Window.Dispatcher.invoke( [action]{ $syncHash .Button1.isEnabled = $true $syncHash .Button2.isEnabled = $true $syncHash .Button3.isEnabled = $true $syncHash .ProgressBar3.IsIndeterminate = $false } ) } $PSinstance = [powershell] :: Create().AddScript( $Code ) $PSinstance .Runspace = $Runspace $job = $PSinstance .BeginInvoke() } #AutoFind all controls $xaml .SelectNodes( "//*[@*[contains(translate(name(.),'n','N'),'Name')]]" ) | ForEach-Object { #New-Variable -Name $_.Name -Value $Form.FindName($_.Name) -Force $syncHash .Add( $_ .Name, $syncHash .Window.Findname( $_ .Name)) } # Click Actions $syncHash .Button1.Add_Click({ Update-Progress -syncHash $syncHash -ProgressNumber 1 }) $syncHash .Button2.Add_Click({ Update-Progress -syncHash $syncHash -ProgressNumber 2 }) $syncHash .Button3.Add_Click({ Update-Progress -syncHash $syncHash -ProgressNumber 3 }) $syncHash .Window.ShowDialog() $Runspace .Close() $Runspace .Dispose() } $PSinstance1 = [powershell] :: Create().AddScript( $Code ) $PSinstance1 .Runspace = $Runspace $job = $PSinstance1 .BeginInvoke()

Useful Articles

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