I am working on a project, this project is based on WPF GUI Wizard. The main idea of the Tool is that it will ask the user to input some data and at the same time perform checks on the provided data. Then after the user input all required data in all wizard pages, the tool will then call subscripts to perform its functionality. Well, WPF cause hangs and unresponsive PowerShell and to overcome this you need to use run spaces. So what I am doing is that I am opening a runspace that the GUI will run in it, then with the wizard, whenever the user provides an input, I validate this input in another runspace.
My problem is that whenever the user provides input, in the GUI runspace I can see the user input but when I call the other runspace I can still see the WPF object but the input provided in this object is not available.
To explain it further Below is a screenshot of the first input box in the GUI and for example, I have input something like (somqfqdn.anything) then I click submit. the GUI itself is running in a runspace called GuiRunspace, once the submit button is clicked I create another runspace called MPSB1Runspace and perform 2 checks (input is not empty, FQDN provided is resolvable).
If I went to the Runspace Debug, in the GuiRunspace if I checked the Inputbox Text I can see the input (somqfqdn.anything) but when I go to the MPSB1Runspace and check the Inputbox Text, I find it empty.
Powershell Runspace Debugging is as follow:
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
Also, I have added a line of code in the MPSB1Runspace to disable a different submit button, but this action is not performed which means that the MPSB1Runspace do not have access to the SyncHash however, i have added the SyncHash to the MPSB1Runspace using the SessionStateProxy.SetVariable.
My Code is as follow:
# 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()
With the above code and the input of somefqdn.anything, I should see an error saying Provided NSX FQDN is not resolvable. Please try again.
Thank you for your help.