Skip to content

Instantly share code, notes, and snippets.

@oising
Created January 21, 2022 16:57
Show Gist options
  • Save oising/0de209c67628101b8e4d3893ffcfe1ae to your computer and use it in GitHub Desktop.
Save oising/0de209c67628101b8e4d3893ffcfe1ae to your computer and use it in GitHub Desktop.
Demonstrate using a nested dispatcher frame to avoid blocking powershell thread (wpf)
# demonstrate using a nested dispatcher frame to avoid blocking powershell thread
# this way you can have full "floating" windows manageable interactively in MTA mode (default) powershell
# Oisin/x0n - feb 9, 2009
Set-StrictMode -Version latest
$ps = [powershell]::create()
$rs = [runspacefactory]::createrunspace()
$rs.ApartmentState = "STA"
$rs.ThreadOptions = "ReuseThread"
$rs.Open()
$ps.Runspace = $rs
$null = $ps.AddScript( {
$xaml = @"
<StackPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<TextBox Name="txt1"></TextBox>
<Button Name="btnTest">Test</Button>
<Button Name="btnExit">Exit</Button>
</StackPanel>
"@
add-type -ass presentationframework, windowsbase -verbose
$global:exit = $false
$global:frame = new-object system.windows.threading.dispatcherframe
$global:handler = { $frame.Continue = $false }
$global:exitHandler = { $global:exit = $true; $frame.Continue = $false; }
$stringReader = new-object system.io.StringReader $xaml
$xmlReader = [system.xml.XmlReader]::Create($stringReader)
$panel = [system.windows.markup.XamlReader]::Load($xmlReader)
$button = $panel.FindName("btnTest")
$button.add_Click( $handler )
register-objectevent -inputobject $button -eventname Click -action {
[Diagnostics.Debug]::WriteLine("Test Click") }
$button = $panel.FindName("btnExit")
$button.add_Click( $exitHandler )
register-objectevent -inputobject $button -eventname Click -action {
[Diagnostics.Debug]::WriteLine("Exit Click") }
$win = new-object system.windows.window
$win.Content = $panel
[Diagnostics.Debug]::WriteLine("Showing Window")
$win.Show();
while (-not $global:exit) {
[Diagnostics.Debug]::WriteLine("Pushing Frame")
[system.windows.threading.dispatcher]::pushframe($frame)
[Diagnostics.Debug]::WriteLine("Frame Popped")
$frame.Continue = $true
}
[Diagnostics.Debug]::WriteLine("Exiting")
#$timer.Stop()
$win.Hide()
})
$ps
$ps.BeginInvoke()
<#
# clean up async stuff (might want this in a script)
$a[0].endinvoke($a[1])
C:\projects\powershell
[155] > $a[0].Stop()
C:\projects\powershell
[156] > $a[0].runspace.dispose()
#>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment