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

PowerShell [XAML/WPF]- Zugriff auf synchronized Hashtable in Runspace

$
0
0

Hallo,

ich habe eine kleine WPF-GUI mit einem Textfeld durch XAML-Code erstellt.
Das Textfeld speicher ich in einer synchronisierten Hashtabelle.

Um Aufgaben Asyncron erledigen zu können, habe ich eine Funktion "Execute-Async" geschrieben.
Der Funktion kann ein Scriptblock übergeben werden, wobei der Scriptblock dann in einem neuem Runspace ausgeführt wird.

Mein Problem ist nun, dass ich in dem asynchronem Scriptblock nicht das Textfeld aus der synchronisierten Hashtabelle auslesen kann (z.B. den Text).
Allerdings kann ich in dem asynchronem Scriptblock dem Textfeld einen neuen Wert geben.

[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
$sync = [Hashtable]::Synchronized(@{ })
$sync.host = $Host

# =========================================================================== #
# = XAML GUI                                                                = #
# =========================================================================== #
[xml]$XAML = @'
<Window
    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"
    Height="300" Width="400" WindowStartupLocation="CenterScreen"><Grid Margin="0,0,-0.4,5.4"><Grid Height="147" Margin="10,18,9.6,0" VerticalAlignment="Top"><Grid.ColumnDefinitions><ColumnDefinition Width="258*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="60*"/></Grid.RowDefinitions><TextBox x:Name="main_textbox_Counter" Height="22" Margin="10,34,15.4,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" BorderBrush="Black" Foreground="Black"/></Grid></Grid></Window>
'@
$XAML.Window.RemoveAttribute('x:Class')
$XAML.Window.RemoveAttribute('mc:Ignorable')
$XAMLReader = New-Object System.Xml.XmlNodeReader $XAML
try{
  $Form=[Windows.Markup.XamlReader]::Load( $XAMLReader )
}
catch{
  Write-Host "Windows.Markup.XamlReader konnte nicht geladen werden. Mögliche Ursache: ungültige Syntax oder fehlendes .net"
}
$sync.Form = $Form

# =========================================================================== #
# = Connect to Controls                                                     = #
# =========================================================================== #
$sync.main_textbox_Counter = $Form.FindName('main_textbox_Counter')

# =========================================================================== #
# = Asynchrones ausführen                                                   = #
# =========================================================================== #
function Execute-Async {
    param (
        [scriptblock] $ScriptBlock,
        [psobject] $Self = @{ },
        [string] $Name = ""
    )
    Write-host "Starte neuen Runspace für Action [$Name]."
    $rs = [runspacefactory]::CreateRunspace()
    $rs.ApartmentState = "STA"
    $rs.ThreadOptions = "ReuseThread"
    $rs.Open()
    $rs.SessionStateProxy.SetVariable("sync", $sync)
    foreach ($var in $Variables.Keys) {
        if ($var -ine 'host') {
            $rs.SessionStateProxy.SetVariable($var, $Variables[$var])
        }
    }
    $script = [PowerShell]::Create()
    [void]$script.AddScript($ScriptBlock)
    $script.Runspace = $rs
    $script.BeginInvoke()
}

# =========================================================================== #
# = Eingeschränkter Zugriff auf Textfeld in Asynchronem Scriptblock         = #
# =========================================================================== #
Execute-Async -Name "Test Schleife" -ScriptBlock {
  for ($i=1; $i -le 10; $i++) {
    if(-not ( $sync.ende)){
      # Textfeld Wert setzen über sync funktioniert
      $sync.Form.Dispatcher.invoke([action]{
        $sync.main_textbox_Counter.Text = $i
      })

      # Ausgabe auf Konsole über sync funktioniert
      $sync.host.UI.WriteLine("[Counter] ... $i")

      # Textfeld auslesen über sync funktioniert nicht...
      $sync.host.UI.WriteErrorLine("[Textbox] ... " + $sync.main_textbox_computername.Text)
    }
    else{
      exit
    }
    Start-Sleep -Milliseconds 1000
  }
}

$sync.main_textbox_Counter.Focus()
[void]$sync.Form.Dispatcher.InvokeAsync{$sync.Form.ShowDialog()}.Wait()
$sync.ende = $true


Viewing all articles
Browse latest Browse all 2314


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