简体   繁体   English

从不同的运行空间调用scriptblock

[英]Calling scriptblock from different runspace

I am working on a project to create a GUI Wizard tool, this GUI Wizard Tool first gets some data from the user and in the same time performing validation (such as connectivity, DNS Resolution, API Connection, etc..). 我正在开发一个创建GUI向导工具的项目,这个GUI向导工具首先从用户获取一些数据并同时执行验证(例如连接,DNS解析,API连接等)。 After the GUI Wizard Tool gets all the required data from the user, then it will start calling other subscripts. GUI向导工具从用户获取所有必需的数据后,它将开始调用其他下标。

To make the GUI Wizard faster and to overcome this unresponsiveness issue, I am using Runspaces, the GUI itself will run in a Runspace and any further tasks (such as performing a validation check) will also run in a different Runspace. 为了使GUI向导更快并克服这种无响应问题,我使用的是Runspaces,GUI本身将在Runspace中运行,任何其他任务(如执行验证检查)也将在不同的Runspace中运行。

To simplify my code and to make it easier and more organized, I am using script blocks. 为了简化我的代码并使其更容易和更有条理,我使用脚本块。 I have created a number of script block within the GUI Runspace to be used whenever a submit button in the GUI is clicked. 我在GUI Runspace中创建了许多脚本块,只要点击GUI中的提交按钮就可以使用它。 for each submits button there would be a different script block and also some submit buttons will execute the same script block. 对于每个提交按钮,将有一个不同的脚本块,并且一些提交按钮将执行相同的脚本块。

My issue is in calling the script blocks. 我的问题是调用脚本块。 whenever I add a script block in an Add_Click action, the script block does not get executed, I have tried using Wait-Debugger within the script block and I do not even see any runspace in the InBreakpoint state. 每当我在Add_Click操作中添加脚本块时,脚本块都不会被执行,我尝试在脚本块中使用Wait-Debugger,我甚至看不到InBreakpoint状态下的任何运行空间。

Can you please let me know if I am doing something wrong as I am new to runspaces and WPF in PowerShell. 如果我在PowerShell中遇到runpaces和WPF,那么请问我是否做错了。 Thank you for your help. 谢谢您的帮助。

#   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(@{ })
$Global:GuiHash.IPCehckPattern = $IPCehckPattern #  Add the IPCehckPattern Variable to be used within other runspaces

#   Crate the Runspace that will be used for the GUI and configure settings. After, Open the Runspace and import variables.
#   You must import variables that will be used in other Runspaces, thus importing the required variables to this Runspace.
$GuiRunspace =[runspacefactory]::CreateRunspace()
$GuiRunspace.ApartmentState = "STA"
$GuiRunspace.ThreadOptions = "ReuseThread"         
$GuiRunspace.Open()
$GuiRunspace.SessionStateProxy.SetVariable("GuiHash",$Global:GuiHash)  
$GuiRunspace.SessionStateProxy.SetVariable("XamlFilesArray",$XamlFilesArray)

#   Create a PowerShell Session and add it to the Runspace.
$GuiPSSession = [PowerShell]::Create()
$GuiPSSession.Runspace = $GuiRunspace

#   Create the GUI PowerShell Session ScriptBlock. This will be the main code of the tool.
[void]$GuiPSSession.AddScript({
    $ScriptBlockMainPageSubmitButton1 = {

        #   This Script block will be called when the first Submit Button in the Main page is clicked.
        #   This will handle the NSX Manager FQDN and perform the required checks
        #   Actions this Script Block will perform are as follow:
        #       1- Check if the input value is empty, if so print error.
        #       2- Check if the Provided FQDN is resolvable.
        #       3- Check if the provided FQDN is reachable on port 443.

        Param($GuiHash)

        Process {
            # Check if WizardMainPageInputBox2 is enabled and if so then disable it.
            If ($GuiHash.WizardMainPageInputBox2.IsEnabled -Eq "False") {$GuiHash.WizardMainPageInputBox2.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageInputBox2.IsEnabled= "True"})}

            # Check if the input data is empty and if so Write Error
            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
                $GuiHash.WizardMainPageInputBox1.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageInputBox1.Text = "NSX Manager FQDN:"})   #   Revert Text in InputBox to default.
            }   Else {
                    # Check if the input FQDN from WizardMainPageInputBox1 is resolvable and if not print error
                    If (!(Resolve-DnsName -Name $GuiHash.WizardMainPageInputBox1.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
                        $GuiHash.WizardMainPageInputBox1.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageInputBox1.Text = "NSX Manager FQDN:"})   #   Revert Text in InputBox to default.
                    }   Else {
                            # Check Reachability of provided FQDN using port 443.
                            # Print Activity Message.
                            $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Foreground= "Green"})    #   Make Sure Printing Color is Green.
                            $GuiHash.WizardMainPageErrorMessage.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageErrorMessage.Text = "Please wait while checking reachability."})  #   Print Message

                            If (!((Test-NetConnection $NsxManagerFQDN -Port 443 -WarningAction SilentlyContinue).TcpTestSucceeded)) {
                                # Print Error and reset the Inputbox text to default.
                                $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 reachable over port 443. Please try again."})       #   Print Error
                                $GuiHash.WizardMainPageInputBox1.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageInputBox1.Text = "NSX Manager FQDN:"})       #   Revert Text in InputBox to default.
                            }   Else {
                                    # Print Success, enable WizardMainPageInputBox2, Disable WizardMainPageSubmitButton1 and add NSX FQDN to Sync Hash
                                    $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
                                    $GuiHash.WizardMainPageSubmitButton1.Dispatcher.Invoke([action]{$GuiHash.WizardMainPageSubmitButton1.IsEnabled= "False"})   #   Disable WizardMainPageSubmitButton1
                                    $GuiHash.NsxManagerFQDN = $GuiHash.WizardMainPageInputBox1.Text     #   Add provided NSX FQDN to GuiHash
                                }
                        }
                }
        }
    }
    #   Run a ForEach Loop to Read each Xaml Page, load the page and lastly add each node within the Xaml to the (GuiHash).
    ForEach ($File in $XamlFilesArray) {
        $TempReadXamlFile=(New-Object System.Xml.XmlNodeReader $File)   #   Read Xaml Page
        $TempWindowForm=[Windows.Markup.XamlReader]::Load($TempReadXamlFile)    #   Load the Wizard XAML Files in a GUI Form
        $File.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object {$Global:GuiHash.Add($_.Name, $TempWindowForm.FindName($_.Name))}    #   Add all XAML Nodes to the HashTable
    }

    #   Set the First page on the Wizard Window to be the WizardMainPageGrid.


$Global:GuiHash.WizardFram.NavigationService.Navigate($Global:GuiHash.WizardMainPageGrid) | Out-Null
$Global: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({$ScriptBlockMainPageSubmitButton1}).AddArgument($Global:GuiHash)
                $ExecScriptObject = $MPSB1PSSesion.BeginInvoke()
            })
#   Show Wizard Window.
        $Global:GuiHash.WizardMainWindow.ShowDialog() | Out-Null

    })  

    $ShowGui = $GuiPSSession.BeginInvoke()

my expectations are when I click on the input box and provide an incorrect FQDN with the GUI will error out with the issue it has seen. 我的期望是,当我点击输入框并提供不正确的FQDN时,GUI会出现问题而出错。

After performing a couple of tests and checks, it turned out that the issue is very simple and it was all my fault. 在进行了几次测试和检查之后,事实证明问题非常简单,这完全是我的错。 When I was calling the AddScript I was using ({}) however you should have only used (). 当我调用我正在使用的AddScript({})时,你应该只使用()。 so after removing the {} and making it only (), it works fine. 所以删除{}并使它只有()后,它工作正常。 As an example, 举个例子,

            $Global: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($ScriptBlockMainPageSubmitButton1).AddArgument($Global:GuiHash)
                $ExecScriptObject = $MPSB1PSSesion.BeginInvoke()
            })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM