Quantcast
Channel: Windows PowerShell Forum
Viewing all articles
Browse latest Browse all 2314

WPF Runspaces and shared variables

$
0
0

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()


Viewing all articles
Browse latest Browse all 2314


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>