Hi there,
i have a problem with shared variables in runspaces with wpf forms.
I habe a wpf form with a button and a listbox. On the listbox i have a menuitem to export the results from the listbox.
When i click on the button i start a runspace, that gets some information (in the example i just do a get-service) and writes them to the listbox.
To have the possiblity to do an export of the items in the list box with all of the attributes i want to write the results of the command (get-service) to a shared variable that i can use in the wpf form later.
How it should work:
- Click Button
--> Start Runspace and call get-service (Search Button and Export-csv will be set to isenabled=false)
--> Write the results to a shared variable
--> Add the results to the listbox within the runspace
--> When runspace finished set search Button and Export-csv to isenabled=true
- Click ExportCSV
--> export the results from the shared variable with all attributes
Within the runspace i can see that the variable is filled correctly and i can add the results to the listbox or a text field in the wpf gui. The problem is, that when i try to use the shared variable outside the runspace it is empty.
If i do a similar thing without wpf gui the sharedvariable is accesible from my powershell session but wpf it wont work.
I am really stuck here and don't get a way to manage it. Can you please provide some help/ideas how to do it.
The global variable handle just was for testing issues.
Thanks in advance.
Regards,
Tom
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") #region Load XAML [xml]$script:XAMLTest = @"<Window x:Class="Test.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Test" mc:Ignorable="d" Title="Test" Height="479.303" Width="320.697" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Background="White"><Grid Margin="0,1,2,-1" Background="#FFF0F0F0"><Button x:Name="btn_search" Content="Search" HorizontalAlignment="Left" Margin="111,204,0,0" VerticalAlignment="Top" Width="75" FontSize="12" RenderTransformOrigin="3.108,9.031"/><ListBox x:Name="lst_search" HorizontalAlignment="Left" Height="189" Margin="27,10,0,0" VerticalAlignment="Top" Width="269"><ListBox.ContextMenu><ContextMenu AllowDrop="True"><MenuItem x:Name="lmi_exportcsv" Header="Export to CSV" IsEnabled="True"/></ContextMenu></ListBox.ContextMenu></ListBox><TextBox x:Name="txt_message" HorizontalAlignment="Left" Height="155" Margin="10,270,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="286" IsReadOnly="True" Background="#FFF0F0F0" VerticalScrollBarVisibility="Auto"/></Grid></Window>"@ -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window' #region Load Form try { $TestForm = [Windows.Markup.XamlReader]::Load( (New-Object System.Xml.XmlNodeReader $XAMLTest) ) } catch { Write-Host "Cannot load Windows.Markup.XamlReader" } $XAMLTest.SelectNodes("//*[@Name]") | ForEach-Object {Set-Variable -Name ($_.Name) -Value $TestForm.FindName($_.Name)} #endregion Load Form #region variables $services = @() $script:sharedData = [HashTable]::Synchronized(@{}) #endregion variables #region functions function Invoke-ServiceSearch{ [CmdletBinding()] param ( [parameter(Position=0, Mandatory=$false)] $Testform, [parameter(Position=1, Mandatory=$false)] $lst_search, [parameter(Position=2, Mandatory=$false)] $btn_search, [parameter(Position=3, Mandatory=$false)] $txt_message, [parameter(Position=4, Mandatory=$false)] $lmi_exportcsv, [parameter(Position=5, Mandatory=$false)] $services ) $code = { $shareddata.services = Get-Service $sharedData.testform.Dispatcher.invoke([action]{$null = $sharedData.lst_search.ItemsSource = $sharedData.services},'Normal') $sharedData.testform.Dispatcher.invoke([action]{$null = $sharedData.txt_message.AppendText("Runspace: $($Shareddata.services.Name)")}) #$sharedData.testform.Dispatcher.invoke([action]{$null = $sharedData.lmi_exportcsv.IsEnabled="True"}) } #region adding variables for use in new runspace $shareddata = @{ testform = $testform lst_search = $lst_search btn_search = $btn_search txt_message = $txt_message services = $services error = $error } #endregion adding variables #generate a new runspace $runspace = [RunSpaceFactory]::CreateRunspace() $runspace.ApartmentState = 'STA' $runspace.ThreadOptions = 'ReuseThread' $runspace.Open() #add shared variable to runspace $runspace.SessionStateProxy.setVariable("sharedData", $sharedData) #generate a new psthread and add script code $ps = [PowerShell]::Create().AddScript($code) $ps.Runspace = $runspace $global:handle = $ps.BeginInvoke() } #endregion functions $btn_search.Add_Click{ $SearchParams = @{ testform = $TestForm btn_search = $btn_search lst_search = $lst_search txt_message = $txt_message lmi_exportcsv = $lmi_exportcsv services = $services } Invoke-ServiceSearch @SearchParams } $lmi_exportcsv.Add_Click{ $txt_message.AppendText("`nMain: $($shareddata.services.Name)") } $null = $TestForm.ShowDialog()