使用Powershell作业更新WPF GUI

时间:2018-05-07 15:22:13

标签: multithreading powershell 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变量的控件。

我试图理解为什么我开始的Job在计算完成时没有更新我的标签。它实际上什么也没做。

我是Powershell工作的新手,我想知道是否有一些我不知道的事情。

1 个答案:

答案 0 :(得分:1)

这是我在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函数。