wpf - 从不同的运行空间调用脚本块
问题描述
我正在开发一个创建 GUI 向导工具的项目,这个 GUI 向导工具首先从用户那里获取一些数据,同时执行验证(例如连接、DNS 解析、API 连接等)。GUI 向导工具从用户那里获得所有需要的数据后,它将开始调用其他下标。
为了使 GUI 向导更快并克服这个无响应问题,我使用了运行空间,GUI 本身将在运行空间中运行,任何进一步的任务(例如执行验证检查)也将在不同的运行空间中运行。
为了简化我的代码并使其更容易和更有条理,我使用了脚本块。我在 GUI 运行空间中创建了许多脚本块,以便在单击 GUI 中的提交按钮时使用。对于每个提交按钮,都会有一个不同的脚本块,并且一些提交按钮将执行相同的脚本块。
我的问题是调用脚本块。每当我在 Add_Click 操作中添加脚本块时,脚本块都不会被执行,我尝试在脚本块中使用 Wait-Debugger,我什至看不到任何处于 InBreakpoint 状态的运行空间。
您能否让我知道我是否做错了什么,因为我是 PowerShell 中的运行空间和 WPF 的新手。谢谢您的帮助。
# 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()
我的期望是,当我单击输入框并使用 GUI 提供不正确的 FQDN 时,它所看到的问题会出错。
解决方案
在进行了几次测试和检查后,事实证明问题很简单,都是我的错。当我调用 AddScript 时,我使用的是 ({}),但是您应该只使用 ()。所以在删除 {} 并使其仅 () 后,它工作正常。举个例子,
$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()
})
推荐阅读
- flutter - 自 .dart_tool/package_config.json 文件生成后 pubspec.lock 文件已更改,请再次运行“pub get”
- css-selectors - p:nth-child(even) 和 p:nth-child(odd) 失去计数,中间 div 放置在几个之后
的
- java - 纵横比始终为 1.0
- python - 截屏时防止硒使用alt-tab
- verilog - 在verilog中将线向量转换为整数
- ceph - pvc 卡在等待创建卷的等待中,无论是通过外部配置程序“rook-ceph.rbd.csi.ceph.com”还是手动创建
- javascript - 如何在点击最后一页后最初只显示两页下一页页码应显示在谷歌图表数据表中
- svelte - Splidejs自动播放不适用于svelte上的第一个视图
- count - 用VB6计算文件夹和子文件夹中的所有文件
- java - 如何在不使用 setnumbers 方法的情况下在 main 中引用我的整数值