使用Start-WPFJob有没有办法将事件发送到父作业? [英] Is there a way to send events to the parent job when using Start-WPFJob?
问题描述
我想从父级Powershell脚本启动一个非阻塞的UI,并接收来自子作业的按钮点击的UI消息。我有这种使用WinForms的信息,但是我更喜欢使用 ShowUI ,因为它的代码少了多少需要创建一个基本的UI。不幸的是,我没有找到一种使用ShowUI将消息发送回父工作的方法。
I would like to launch a non-blocking UI from a parent Powershell script and receive UI messages like button clicks from the child job. I have this kind of messaging working using WinForms, but I prefer to use ShowUI because of how much less code it takes to create a basic UI. Unfortunately, though, I haven't found a way to send messages back to the parent job using ShowUI.
使用 Start-Job 将事件从小孩转发到父工作是相当简单的。以下是一个例子:
Using Start-Job, forwarding events from a child to a parent job is rather straightforward. Here is an example:
$pj = Start-Job -Name "PlainJob" -ScriptBlock {
Register-EngineEvent -SourceIdentifier PlainJobEvent -Forward
New-Event -SourceIdentifier PlainJobEvent -MessageData 'My Message'
}
Wait-Event | select SourceIdentifier, MessageData | Format-List
正如所料,打印出来:
SourceIdentifier : PlainJobEvent
MessageData : My Message
[不工作]使用Start-WPFJob时转发事件
使用 Start-WPFJob 似乎没有将事件从小孩转发到父级。考虑这个例子:
[Does Not Work] Forwarding Events When Using Start-WPFJob
Using Start-WPFJob, on the other hand, does not seem to forward events from the child to the parent. Consider this example:
Import-Module ShowUI
$wj = Start-WPFJob -ScriptBlock {
Register-EngineEvent -SourceIdentifier MySource -Forward
New-Button "Button" -On_Click {
New-Event -SourceIdentifier MySource -MessageData 'MyMessage'
}
}
Wait-Event | select SourceIdentifier, MessageData | Format-List
运行此示例生成此窗口:
Running this example produces this window:
点击然而,在按钮上,不会在父工作中产生一个事件。
Clicking on the button, however, does not yield an event in the parent job.
- 为什么
- 有没有其他方法可以使用ShowUI来生成一个按钮以非阻塞的方式接收事件?
推荐答案
我不能得到引擎事件到目前为止正确转发(实际上,我甚至不能让他们做任何事情,据我所知),我想你最好的选择是运行WPFJob,而不是新事件更新$窗口UIValue,然后从您的主运行空间,而不是等待事件,在循环中使用Update-WPFJob。
I can't get engineevents to forward properly so far (actually, I can't even get them to do anything, as far as I can tell), I think your best bet is to run the WPFJob, and instead of New-Event, update the $Window UIValue, and then from your main runspace, instead of Wait-Event, use Update-WPFJob in a loop.
我将这个功能粘贴到模块中(实际上,我会补充一下对于源代码控制的1.5版本,但尚未发布):
I would stick this function into the module (actually, I will add it for the 1.5 release that's in source control but not released yet):
function Add-UIValue {
param(
[Parameter(ValueFromPipeline=$true)]
[Windows.FrameworkElement]
$Ui,
[PSObject]
$Value
)
process {
if ($psBoundParameters.ContainsKey('Value')) {
Set-UIValue $UI (@(Get-UIValue $UI -IgnoreChildControls) + @($Value))
} else {
Set-UIValue -Ui $ui
}
}
}
然后,这样的东西:
$job = Start-WPFJob {
Window {
Grid -Rows "1*", "Auto" {
New-ListBox -Row 0 -Name LB -Items (Get-ChildItem ~ -dir)
Button "Send" -Row 1 -On_Click { Add-UIValue $Window $LB.SelectedItem }
}
} -SizeToContent "Width" -MinHeight 800
}
每次点击时,将将所选项目添加到UI输出(如果您运行该窗口而没有任务,然后单击该按钮几次,然后关闭窗口,您将获得两个输出)
Every time you click, would add the selected item to the UI output (if you run that window without the job and click the button a couple of times, then close the window, you'll get two outputs).
然后,您可以在主机中执行类似这样的操作,而不是等待事件:
Then you can do something like this in the host instead of Wait-Event:
do {
Update-WPFJob -Job $job -Command { Get-UIValue $Window -IgnoreChildControls } -OutVariable Output
Start-Sleep -Mil 300
} while (!$Output)
这篇关于使用Start-WPFJob有没有办法将事件发送到父作业?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!