This script will create a Progress Bar window using Windows Presentation Foundation. 

In the original code, when closing the window/form by pressing the "X" button, powershell would freeze/crash when invoking Dispatcher. To resolve the issue, I cancel the closing of the window and make sure no other Dispatcher is executed. Then I close the window and the namespace.

Updated to work on Powershell 2.0 and up.

Dont forget to Rate and write any comments in the Q&A.. curious to know what you guys think!

Credit for original code: Script New-ProgressBar from Rhys W Edwards.
PowerShell
Edit|Remove
<# 
.SYNOPSIS   
    This script is used to create a  progress bar 
.DESCRIPTION   
    This script uses a Powershell Runspace to create and manage a WPF progress bar that can be manipulated to show 
    script progress and details.  There are no arguments for this script because it is just an example of how this can be done.   
    The components within the script are what's important for setting this up for your own purposes. 
.NOTES   
    Version        : 2.0 
    Author        : Marc R Kellerman 
    Email        : mkellerman@outlook.com   
    Credit Due    : Rhys Edwards & Boe Prox wrote in detail about this method of using runspaces and forms, I just applied it to  
                  a very common problem 
    Link        : https://gallery.technet.microsoft.com/scriptcenter/New-ProgressBar-8468da5c/view/Discussions#content 
#> 
 
Function Load-Window { 
 
    [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') 
    $global:syncHash = [hashtable]::Synchronized(@{}) 
    $global:newRunspace =[runspacefactory]::CreateRunspace() 
    $newRunspace.ApartmentState = "STA" 
    $newRunspace.ThreadOptions = "ReuseThread"           
    $newRunspace.Open() 
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)           
    $newRunspace.SessionStateProxy.SetVariable("newRunspace",$newRunspace)           
    $global:psCmd = [PowerShell]::Create().AddScript({    
    [xml]$xaml = @" 
    <Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        x:Name="Window" Title="Progress..." WindowStartupLocation = "CenterScreen" 
        Width = "335" Height = "130" ShowInTaskbar = "True"> 
        <Grid> 
            <ProgressBar x:Name = "ProgressBar" Height = "20" Width = "300" HorizontalAlignment="Left" VerticalAlignment="Top" Margin = "10,10,0,0"/> 
            <Label x:Name = "Label1" Height = "30" Width = "300" HorizontalAlignment="Left" VerticalAlignment="Top" Margin = "10,35,0,0"/> 
            <Label x:Name = "Label2" Height = "30" Width = "300" HorizontalAlignment="Left" VerticalAlignment="Top" Margin = "10,60,0,0"/> 
        </Grid> 
    </Window> 
"@ 
  
        $reader=(New-Object System.Xml.XmlNodeReader $xaml) 
        $syncHash.Window=[Windows.Markup.XamlReader]::Load( $reader ) 
 
        $syncHash.IsClosed = $False 
        $syncHash.Error = $Error 
 
        $syncHash.ProgressBar = $syncHash.Window.FindName("ProgressBar") 
        $syncHash.Label1 = $syncHash.Window.FindName("Label1") 
        $syncHash.Label2 = $syncHash.Window.FindName("Label2") 
        $syncHash.Window.Add_Closing( { If ($syncHash.IsClosed -ne $True) { $_.Cancel = $True$syncHash.IsClosed = $True; } } )  
        $syncHash.Window.ShowDialog() | Out-Null 
    }) 
    $psCmd.Runspace = $newRunspace 
    $data = $psCmd.BeginInvoke() 
    While (!($syncHash.Window.IsInitialized)) { Start-Sleep -S 1 } 
 
} # End Function Load-Window 
 
Function Update-Window { 
    Param ( 
        $Control, 
        $Property, 
        $Value, 
        [switch]$AppendContent 
    ) 
 
    $syncHash.IsRunning = $true 
 
    Write-Warning "$Control . $Property = $Value" 
     
    If ($newRunspace.RunspaceStateInfo.State -ne 'Opened') { Return $False } 
 
    # User is closing the window. 
    If ($syncHash.IsClosed) { $Property = "Close" } 
 
    # This is kind of a hack, there may be a better way to do this 
    If ($Property -eq "Close") { 
 
        $syncHash.IsClosed = $True 
        If($PSVersionTable.PSVersion.Major -eq 2) { 
          $Global:syncHash.$Control.Dispatcher.invoke(“Normal”,[action]{ $Global:syncHash.Window.Close() }) 
        } Else { 
          $Global:syncHash.Window.Dispatcher.invoke([action]{ $Global:syncHash.Window.Close() },"Normal") 
        } 
 
        $newRunspace.Close() 
        Return $False 
    } 
   
    # This updates the control based on the parameters passed to the function 
    If (($Control-and ($Property-and ($Value)) { 
 
        If($PSVersionTable.PSVersion.Major -eq 2) { 
            $Global:syncHash.$Control.Dispatcher.invoke(“Normal”,[action]{  
            If ($PSBoundParameters['AppendContent']) { $syncHash.$Control.AppendText($Value) }  
                                                Else { $syncHash.$Control.$Property = $Value } 
            }) 
        } Else { 
            $Global:syncHash.Window.Dispatcher.invoke([action]{  
            If ($PSBoundParameters['AppendContent']) { $syncHash.$Control.AppendText($Value) }  
                                                Else { $syncHash.$Control.$Property = $Value } 
            },"Normal") 
        } 
 
    } 
 
    Return $True 
 
} # End Function Update-Window 
 
Function Close-Window { 
 
    Update-Window Window Close | Out-Null 
 
} # End Function Close-Window 
 
Function Update-ProgressBar { 
    Param ( 
        [int]$Percent, 
        [string]$Label1Text, 
        [string]$Label2Text 
    ) 
 
    If ($Label1Text) { $Result = Update-Window Label1 Content $Label1Text } 
    If ($Label2Text) { $Result = Update-Window Label2 Content $Label2Text } 
    If ($Percent)    { $Result = Update-Window ProgressBar Value $Percent } 
 
    Return $Result 
 
} #End Function Update-ProgressBar 
 
 
 
# Create the window form in a different namespace 
Load-Window 
 
For ($i = 0; $i -lt 100; $i++) { 
 
    # Update-Window will return if the form/window is active 
    $Result = Update-Window 
 
    If ($i.ToString()[-1] -eq "0") { 
        #Update the progressbar 
        $Result = Update-ProgressBar -Percent $i -Label1Text "$i / 100" 
    } 
 
    #If the window is close, stop the loop 
    If ($Result -eq $False) { Break } 
 
    Sleep -Milliseconds 100 
 
} 
 
Close-Window