使用Start-WPFJob有没有办法将事件发送到父作业? [英] Is there a way to send events to the parent job when using Start-WPFJob?

查看:166
本文介绍了使用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.


  1. 为什么

  2. 有没有其他方法可以使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆