添加到SyncHash的Powershell WFP对象不会传递到不同的运行空间

时间:2019-05-19 21:03:55

标签: wpf powershell synchronization runspace

我正在一个项目上,该项目基于WPF GUI向导。该工具的主要思想是,它将要求用户输入一些数据,同时对提供的数据进行检查。然后,在用户在所有向导页面中输入了所有必需的数据之后,该工具将调用下标以执行其功能。好吧,WPF导致挂起且PowerShell无法响应,要解决此问题,您需要使用运行空间。因此,我要做的是打开一个将在其中运行GUI的运行空间,然后使用向导,每当用户提供输入时,我都会在另一个运行空间中验证此输入。

我的问题是,每当用户提供输入时,在GUI运行空间中我都可以看到用户输入,但是当我调用其他运行空间时,我仍然可以看到WPF对象,但是此对象中提供的输入不可用。

进一步解释下面是GUI中第一个输入框的屏幕快照,例如,我输入了类似(somqfqdn.anything)之类的内容,然后单击提交。 GUI本身在名为GuiRunspace的运行空间中运行,一旦单击“提交”按钮,我将创建另一个称为MPSB1Runspace的运行空间,并执行2次检查(输入不为空,提供的FQDN可解析)。

enter image description here

如果我去了Runspace调试,如果在GuiRunspace中选中了Inputbox Text,我可以看到输入(somqfqdn.anything),但是当我进入MPSB1Runspace并检查Inputbox Text时,我发现它为空。

Powershell Runspace调试如下:

PS C:\Users\Administrator> Debug-Runspace Runspace32
Debugging Runspace: Runspace32
To end the debugging session type the 'Detach' command at the debugger prompt, or type 'Ctrl+C' otherwise.

Stopped at: $MPSB1Runspace = [runspacefactory]::CreateRunspace()
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> $GuiHash.WizardMainPageInputBox1.Text
somqfqdn.anything

[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 
Stopped at: $MPSB1PSSesion = [powershell]::Create()
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 
Stopped at: $MPSB1PSSesion.runspace = $MPSB1Runspace
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 
Stopped at: $MPSB1Runspace.Open()
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 
Stopped at: $MPSB1Runspace.SessionStateProxy.SetVariable("GuiHash",$Global:GuiHash)
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 
Stopped at: [void]$MPSB1PSSesion.AddScript({
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 
Stopped at: })
[DBG]: [Process:5900]: [Runspace32]: PS C:\Users\Administrator>> 

PS C:\Users\Administrator> Debug-Runspace Runspace34
Debugging Runspace: Runspace34
To end the debugging session type the 'Detach' command at the debugger prompt, or type 'Ctrl+C' otherwise.

Stopped at: If ($GuiHash.WizardMainPageInputBox1.Text.Length -Eq 0) {
[DBG]: [Process:5900]: [Runspace34]: PS C:\Users\Administrator>> $GuiHash.WizardMainPageInputBox1.Text

[DBG]: [Process:5900]: [Runspace34]: PS C:\Users\Administrator>> $Global:GuiHash.WizardMainPageInputBox1.Text

此外,我在MPSB1Runspace中添加了一行代码以禁用其他提交按钮,但是未执行此操作,这意味着MPSB1Runspace无法访问SyncHash,但是,我已将SyncHash添加到MPSB1Runspace使用SessionStateProxy.SetVariable。

我的代码如下:

#   Create an Array that will hold all the XAML pages variables.
$XamlFilesArray = @($WizardMainWindowXaml, $WizardMainPageXaml, $WizardVCPageXaml, $WizardHostingVCPageXaml, $WizardControllerPageXaml, $WizardPrimaryNsxPageXaml, $WizardPrimaryVCPageXaml, $WizardFinalPageXaml)
#   Create  Sync HashTable (GuiHash) to allow readability across different Runscpases and add required variables.
$Global:GuiHash = [hashtable]::Synchronized(@{ })
#   Crate the Runspace that will be used for the GUI
$GuiRunspace =[runspacefactory]::CreateRunspace()
$GuiRunspace.ApartmentState = "STA"
$GuiRunspace.ThreadOptions = "ReuseThread"         
$GuiRunspace.Open()
$GuiRunspace.SessionStateProxy.SetVariable("GuiHash",$Global:GuiHash) 
#   Create a PowerShell Session and add it to the Runspace.
$GuiPSSession = [PowerShell]::Create()
$GuiPSSession.Runspace = $GuiRunspace
#   Create the GUI PowerShell Session ScriptBlock.
[void]$GuiPSSession.AddScript({

    ####Some the rest of the code that will build the GUI and load XAML Files

    #   Configure WizardMainPageSubmitButton1
    $GuiHash.WizardMainPageSubmitButton1.Add_Click({
        # Create new Runspace for this task. 
        $MPSB1Runspace = [runspacefactory]::CreateRunspace()
        $MPSB1PSSesion = [powershell]::Create()
        $MPSB1PSSesion.runspace = $MPSB1Runspace
        $MPSB1Runspace.Open()
        $MPSB1Runspace.SessionStateProxy.SetVariable("GuiHash",$Global:GuiHash)
        [void]$MPSB1PSSesion.AddScript({
            If ($GuiHash.WizardMainPageInputBox1.Text.Length -Eq 0) {
                $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Foreground= "Red"})  #   Make Sure Printing Color is Red.
                $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Text = "Provided Data is empty, please provide NSX FQDN."})  #   Print Error
            }   Else {
                    # Check if the input FQDN from WizardMainPageInputBox1 is resolvable and if not print error
                    If (!(Resolve-DnsName -Name $GuiHash.WizardMainPageInputBox1.Text.Text -ErrorAction SilentlyContinue)) {
                        $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Foreground= "Red"})  #   Make Sure Printing Color is Red.
                        $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Text = "Provided NSX FQDN is not resolvable. Please try again."})    #   Print Error                  
                    }   Else {
                            # Print Success, enable WizardMainPageInputBox2
                            $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Foreground= "White"})        #   Make Sure Printing Color is White.
                            $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Text = "Provided NSX FQDN confirmed. Please provide credentials."})  #   Print Message
                            $GuiHash.WizardMainPageInputBox2.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageInputBox2.IsEnabled= "True"})    #   Enable WizardMainPageInputBox2 to continue

                        }
                }   
        }).BeginInvoke()   

    }).BeginInvoke()  

    #   Show Wizard Window.
    $Global:GuiHash.WizardMainWindow.ShowDialog() | Out-Null

}).BeginInvoke()    

$ShowGui = $GuiPSSession.BeginInvoke()

使用上面的代码和somefqdn.anything的输入,我应该看到一条错误消息,提示“提供的NSX FQDN无法解析”。请重试。

谢谢您的帮助。

1 个答案:

答案 0 :(得分:0)

经过一些测试,我能够解决此问题。当我调用第二个运行空间时,我已将文本框的内容传递给另一个变量,并将其添加到第二个reunspace setvariable

代码如下:

                $MPSB1Runspace = [runspacefactory]::CreateRunspace()
                $MPSB1PSSesion = [powershell]::Create()
                $MPSB1PSSesion.runspace = $MPSB1Runspace
                $MPSB1Runspace.Open()
                $MPSB1Runspace.SessionStateProxy.SetVariable("GuiHash",$Global:GuiHash)
                $MPSB1Runspace.SessionStateProxy.SetVariable("NsxFqdn",$Global:GuiHash.WizardMainPageInputBox1.Text)
                [void]$MPSB1PSSesion.AddScript({
                       your code goes here and now $NsxFqdn have the input value
                })