使用 Powershell 作业更新 WPF GUI
Update a WPF GUI using Powershell Jobs
我一直在尝试为我的个人 Powershell 脚本创建响应式 GUI。我想出了一个在网上被高度讨论的问题:冻结 GUI(因为 Powershell 是单线程的)。
与此类似 problem,但我的案例特定于 Powershell。我成功地实现了一个基于 Powershell 的解决方案,用于创建依赖于 XAML 表单的 GUI。现在,让我们考虑一下这段代码:
#EVENT Handler
$Somebutton.add_Click({
$SomeLabel.Content = "Calculating..."
Start-Job -ScriptBlock {
#Computation that takes time
#...
$SomeLabel.Content = "Calculated value"
}
})
#Show XAML GUI
$xamlGUI.ShowDialog() | out-null
xamlGUI
是表单本身,$Somebutton
/$SomeLabel
是我能够从 xaml 读取并转换为 Powershell 变量的控件。
我想了解为什么我开始的作业在计算完成后没有更新我的标签。它实际上什么都不做。
我是 Powershell 工作的新手,我想知道我是否遗漏了什么。
这是我在 PowerShell 中用于反应式 WPF 表单的小样板文件:
# Hide yo console
$SW_HIDE, $SW_SHOW = 0, 5
$TypeDef = '[DllImport("User32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);'
Add-Type -MemberDefinition $TypeDef -Namespace Win32 -Name Functions
$hWnd = (Get-Process -Id $PID).MainWindowHandle
$Null = [Win32.Functions]::ShowWindow($hWnd,$SW_HIDE)
# Define your app + form
Add-Type -AssemblyName PresentationFramework
$App = [Windows.Application]::new() # or New-Object -TypeName Windows.Application
$Form = [Windows.Markup.XamlReader]::Load(
[Xml.XmlNodeReader]::new([xml]@'
WPF form definition goes here
'@)
)
# or ::Load((New-Object -TypeName Xml.XmlNodeReader -ArgumentList ([xml]@'
#wpfdef
#'@))
#)
# Fixes the "freeze" problem
function Update-Gui {
# Basically WinForms Application.DoEvents()
$App.Dispatcher.Invoke([Windows.Threading.DispatcherPriority]::Background, [action]{})
}
# Event handlers go here
$Form.add_Closing({
$Form.Close()
$App.Shutdown()
Stop-Process -Id $PID # or return your console: [Win32.Functions]::ShowWindow($hWnd,$SW_SHOW)
})
# Finally
$App.Run($Form)
记得在您的应用关闭时进行清理:
$Form.Close()
$App.Shutdown()
Stop-Process -Id $PID
只要您需要反映对 GUI 的更改,请调用 Update-Gui
函数。
我一直在尝试为我的个人 Powershell 脚本创建响应式 GUI。我想出了一个在网上被高度讨论的问题:冻结 GUI(因为 Powershell 是单线程的)。
与此类似 problem,但我的案例特定于 Powershell。我成功地实现了一个基于 Powershell 的解决方案,用于创建依赖于 XAML 表单的 GUI。现在,让我们考虑一下这段代码:
#EVENT Handler
$Somebutton.add_Click({
$SomeLabel.Content = "Calculating..."
Start-Job -ScriptBlock {
#Computation that takes time
#...
$SomeLabel.Content = "Calculated value"
}
})
#Show XAML GUI
$xamlGUI.ShowDialog() | out-null
xamlGUI
是表单本身,$Somebutton
/$SomeLabel
是我能够从 xaml 读取并转换为 Powershell 变量的控件。
我想了解为什么我开始的作业在计算完成后没有更新我的标签。它实际上什么都不做。
我是 Powershell 工作的新手,我想知道我是否遗漏了什么。
这是我在 PowerShell 中用于反应式 WPF 表单的小样板文件:
# Hide yo console
$SW_HIDE, $SW_SHOW = 0, 5
$TypeDef = '[DllImport("User32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);'
Add-Type -MemberDefinition $TypeDef -Namespace Win32 -Name Functions
$hWnd = (Get-Process -Id $PID).MainWindowHandle
$Null = [Win32.Functions]::ShowWindow($hWnd,$SW_HIDE)
# Define your app + form
Add-Type -AssemblyName PresentationFramework
$App = [Windows.Application]::new() # or New-Object -TypeName Windows.Application
$Form = [Windows.Markup.XamlReader]::Load(
[Xml.XmlNodeReader]::new([xml]@'
WPF form definition goes here
'@)
)
# or ::Load((New-Object -TypeName Xml.XmlNodeReader -ArgumentList ([xml]@'
#wpfdef
#'@))
#)
# Fixes the "freeze" problem
function Update-Gui {
# Basically WinForms Application.DoEvents()
$App.Dispatcher.Invoke([Windows.Threading.DispatcherPriority]::Background, [action]{})
}
# Event handlers go here
$Form.add_Closing({
$Form.Close()
$App.Shutdown()
Stop-Process -Id $PID # or return your console: [Win32.Functions]::ShowWindow($hWnd,$SW_SHOW)
})
# Finally
$App.Run($Form)
记得在您的应用关闭时进行清理:
$Form.Close()
$App.Shutdown()
Stop-Process -Id $PID
只要您需要反映对 GUI 的更改,请调用 Update-Gui
函数。