I wrote a small application using WPF and Runspaces and ran into some difficulties.
$Runspace = [runspacefactory]::CreateRunspace()
$Runspace.ApartmentState = "STA"
$Runspace.ThreadOptions = "ReuseThread"
$Runspace.Open()
$code = {
#Build the GUI
[xml]$xaml = @"
$xaml_code
"@
$syncHash = [hashtable]::Synchronized(@{ })
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$syncHash.Window = [Windows.Markup.XamlReader]::Load($reader)
function RunspaceScript {
param($syncHash, $Servers, $TargetBox)
$syncHash.Host = $host
$Runspace = [runspacefactory]::CreateRunspace()
$Runspace.ApartmentState = "STA"
$Runspace.ThreadOptions = "ReuseThread"
$Runspace.Open()
$Runspace.SessionStateProxy.SetVariable("syncHash", $syncHash)
$Runspace.SessionStateProxy.SetVariable("Servers", $Servers)
$Runspace.SessionStateProxy.SetVariable("TargetBox", $TargetBox)
$code = {
Function Add-OutputBoxLine {
Param ([string]$Message,[string]$Color = "Black")
$syncHash.Window.Dispatcher.invoke(
[action]{
$RichTextRange = New-Object System.Windows.Documents.TextRange($syncHash.$TargetBox.Document.ContentEnd, $syncHash.$TargetBox.Document.ContentEnd)
$RichTextRange.Text = "$Message`r`n"
$RichTextRange.ApplyPropertyValue([System.Windows.Documents.TextElement]::ForegroundProperty, "$Color")
$syncHash.$TargetBox.ScrollToCaret()
}
)
}
$syncHash.Window.Dispatcher.invoke(
[action]{ $syncHash.$TargetBox.Clear(); $syncHash.Start_Switchover.IsEnabled = $False })
if (!$az_connection) {
$az_connection = Connect-AzAccount
}
}
$PSinstance = [powershell]::Create().AddScript($Code)
$PSinstance.Runspace = $Runspace
$PSinstance.Runspace.Name = "SwitchOver"
$job = $PSinstance.BeginInvoke()
}
# Click Actions
$syncHash.Start_Switchover.Add_Click(
{
RunspaceScript -syncHash $syncHash -Servers $syncHash.Servers.Text -TargetBox "Process_Output"
})
$syncHash.Window.ShowDialog()
$Runspace.Close()
$Runspace.Dispose()
}
$PSinstance1 = [powershell]::Create().AddScript($Code)
$PSinstance1.Runspace = $Runspace
$job = $PSinstance1.BeginInvoke()
I want to access variable $az_connection which is inside a runspace which is inside a function "RunspaceScript" from previous execution of that function. Any ideas how it can be achieved?
P.S. I was forced to remove some lines from the script code here because of the rules, don't try to copy and run the code, it will not work.
Probably the easiest way is to add it to $syncHash - $syncHash.AzConnection = $az_connection
. Otherwise you need to return it as output from your scriptblock and then pull the output once the AsyncResult completes.
function RunspaceScript {
param($syncHash, $Servers, $TargetBox)
$syncHash.Host = $host
$Runspace = [runspacefactory]::CreateRunspace()
$Runspace.ApartmentState = 'STA'
$Runspace.ThreadOptions = 'ReuseThread'
$Runspace.Open()
$Runspace.SessionStateProxy.SetVariable('syncHash', $syncHash)
$Runspace.SessionStateProxy.SetVariable('Servers', $Servers)
$Runspace.SessionStateProxy.SetVariable('TargetBox', $TargetBox)
$code = {
Function Add-OutputBoxLine {
Param ([string]$Message, [string]$Color = 'Black')
$syncHash.Window.Dispatcher.invoke(
[action] {
$RichTextRange = New-Object System.Windows.Documents.TextRange($syncHash.$TargetBox.Document.ContentEnd, $syncHash.$TargetBox.Document.ContentEnd)
$RichTextRange.Text = "$Message`r`n"
$RichTextRange.ApplyPropertyValue([System.Windows.Documents.TextElement]::ForegroundProperty, "$Color")
$syncHash.$TargetBox.ScrollToCaret()
}
)
}
$syncHash.Window.Dispatcher.invoke(
[action] { $syncHash.$TargetBox.Clear(); $syncHash.Start_Switchover.IsEnabled = $False })
if (!$az_connection) {
$az_connection = Connect-AzAccount
}
## Output the connection from your scriptblock ##
$az_connection
## OR just add it to your synchronized hashtable ##
$syncHash.AzConnection = $az_connection
}
$PSinstance = [powershell]::Create().AddScript($Code)
$PSinstance.Runspace = $Runspace
$PSinstance.Runspace.Name = 'SwitchOver'
$job = $PSinstance.BeginInvoke()
## Wait for the $code scriptblock to finish ##
While (-not $job.IsCompleted) {
Start-Sleep -Seconds 1
}
## Pass the job to EndInvoke() to receive the output ##
$az_connection = $PSinstance.EndInvoke($job)
## Or access it from your synchronized hashtable ##
$syncHash.AzConnection
}