Top-Themen

Aktuelle Themen (A bis Z)

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

gelöst PowerShell GUI WPF

Mitglied: derhoeppi

derhoeppi (Level 2) - Jetzt verbinden

14.10.2015, aktualisiert 19.10.2015, 2574 Aufrufe, 18 Kommentare

Hallo,

heute habe ich hoffentlich wieder ein einfaches Thema. Und zwar besitzt meiner GUI (WPF) einige Checkboxen und auch eine Progressbar. Während der Laufzeit meines Skriptes, sollen die Checkboxen deaktiviert werden (IsEnabled = $false). Für die Progressbar habe ich ebenfalls eine Funktion die mir den Wert errechnet, der durch die Progressbar abgebildet wird. Die Berechnung und auch der Befehl zum deaktivieren der Checkbox funktioniert, wird mir aber nicht zur Laufzeit in der GUI angezeigt. Den Wert für die Progressbar lasse ich im Hintergrund in der PowerShell Console ausgeben.

Den Aufruf der GUI habe ich sowohl mit einem einfachen ShowDialog() als auch mit der Dispatcher.InvokeAsync({ShowDialog()}) versucht. Das verhalten ändert sich allerdings nicht. Die Anzeige wird während des Skriptes erst aktualisiert, wenn ich durch das Skript eine Messagebox öffne.

Woran kann das liegen?

Gruß
derhoeppi
Mitglied: 122990
14.10.2015, aktualisiert um 13:57 Uhr
Moin,
heute habe ich hoffentlich wieder ein einfaches Thema
Für Anfänger eher ein schwierigeres Thema.
Stichwort MultiThreading während du eine andere Aktion im selben Thread-Kontext ausführst wie die GUI wird sich diese erst wieder aktualisieren wenn deine Aktion fertig ist. Also musst du deine Aktion die du im Hintergrund ausführen willst auch in einem separaten Thread oder Job laufen lassen. Ebenso blockieren Schleifen im Hauptkontext die GUI.

Hier ein paar Beispiele aus dem Forum

Gruß grexit
Bitte warten ..
Mitglied: derhoeppi
14.10.2015 um 14:33 Uhr
Hallo grexit,

okay, dann komme ich doch noch schneller zu einem Thema, welches ich in meinem Skript angehen will - runspace. Ich werde mir mal die Links von Dir und die weiterführenden Links in den Beiträgen durchlesen. Wenn ich Fragen zur Implementierung habe, würde ich mich wieder melden.

Gruß
derhoeppi
Bitte warten ..
Mitglied: derhoeppi
15.10.2015 um 22:16 Uhr
Hallo,

ich habe nun einiges zum Thema Runspace gelesen und auch diverse Beispiele gesehen. Aufgrund diverser Artikel im Internet möchte ich dieses gerne statt PSJob nutzen (aus Performance-Gründen).

Nun bin ich dabei das gelesene in mein Skript einzubauen. Prinzipiell möchte ich den Runspace innerhalb einer Funktion aufrufen. Folgendes habe ich dazu geschrieben.

01.
Function Progressbar {
02.
    Write-Host $Progress
03.
    $syncHash = [hashtable]::Synchronized(@{})
04.
    $syncHash.progress = $PB_Status
05.
    $syncHash.value = $Progress
06.
    $newRunspace =[runspacefactory]::CreateRunspace()
07.
    $newRunspace.Open()
08.
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
09.
    $psCmd = [powershell]::Create()
10.
    $psCmd.Runspace = $newRunspace
11.
    $psCmd.AddScript({
12.
    $syncHash.progress.Value = $syncHash.value
13.
    })
14.
    $psCmd.Runspace = $newRunspace
15.
    $handle = $psCmd.BeginInvoke()
16.
    While (-Not $handle.IsCompleted) {
17.
        Start-Sleep -Milliseconds 100
18.
    }
19.
    $psCmd.EndInvoke($handle)
20.
    $newRunspace.Close()
21.
    $psCmd.Dispose()
22.
}
$PB_Status ist meine Progressbar und $Progress ist ein Integer-Wert den ich zuvor berechnet habe. Wenn ich diese Funktion aufrufe, ändert sich jedoch nichts in der Progressbar, obwohl die Variable $Progress aufsteigende Werte annimmt.
Da ich die Funktion mehrmals in meinem Skript aufrufe - es soll ja auch ein Fortschritt zu erkennen sein - würde mich interessieren, ob ich den Runspace zum Skriptbegin initialisieren kann und dann immer wieder diesen Thread mit dieser Funktion starten kann?

Gruß
derhoeppi
Bitte warten ..
Mitglied: 122990
16.10.2015 um 11:41 Uhr
Leider nutzt du de Hashtable nicht richtig.
Zur Erläuterung:
Die "synchronisierte Hashtable" hat den Zweck das der Sub-Thread Steuerelemente im GUI-Thread ändern kann weil normalerweise ein anderer Thread per Default nicht Threadübergeifend auf Steuerelemente eines anderen Threads zugreifen darf (Cross-Thread-Call). D.h. es wird zuerst eine leere Hashtable erstellt und dann eine Eigenschaft dieser hinzugefügt. Dieser neuen Eigenschaft wird das Progressbar-Objekt deines GUI hinzugefügt.
Diese Eigenschaft ist somit auch automatisch im SubThread erreichbar, es kann also im SubThread der Wert der Progressbar gesetzt werden z.B.
01.
 $syncHash.progress.Value = 50
für 50 Prozent.

In deinem Teil oben machst du einige Fehler wie z.B. das hier hat keinen Nutzen:
01.
$syncHash.value = $Progress
denn du hast ja schon eine Eigenschaft der Hashtable hiermit übergeben:
01.
$syncHash.progress = $PB_Status
Und auf diese Eigenschaft kannst du aus dem SubThread zugreifen wie oben beschrieben. Da es eine synchronized Hashtable ist wird bei einer Änderung daran diese im GUI-Thread ebenfalls aktualisiert, und reflektiert die Änderungen an der Progressbar wieder.

Das ist die ganze Magie dahinter.

Gruß grexit
Bitte warten ..
Mitglied: derhoeppi
16.10.2015 um 12:29 Uhr
Hallo grexit,

ich habe im AddScript Block nur das
01.
$syncHash.progress.Value = 50
eingetragen. Leider ändert sich in der GUI gar nichts. "$syncHash.value = $Progress" habe ich zuvor aus kommentiert. Zum Troubleshooting lasse ich
01.
Write-Host $syncHash.progress.Value
vor und nach dem "$handle = $psCmd.BeginInvoke()" ausgeben. Der Wert beträgt immer 0, obwohl die Funktion mehrmals in meinem Skript aufgerufen wird. Warum die Progressbar keinen anderen Wert annimmt kann ich aktuell nicht nachvollziehen. Du schreibst ja selbst das "$syncHash.progress.Value = 50" eine Veränderung in meiner GUI herbeiführen sollte.

Mit dem "$syncHash.value = $Progress" wollte ich die Hashtabelle um eine Variable $Progress erweitern. In dieser Variable steht mein Wert, den ich der Progressbar zuweisen möchte. Diesen Wert möchte ich gerne in den Sub-Thread geben, damit ich diesen nicht im Sub-Thread berechnen muss. Dazu werte ich den Status von Checkboxen aus, die ich dann auch alle aus dem Sub Thread ansprechen müsste.

Gruß
derhoeppi
Bitte warten ..
Mitglied: 122990
16.10.2015, aktualisiert um 12:48 Uhr
Schau dir das verlinkte Beispiel nochmal ganz genau an und was du vergessen hast. Der Sinn und Zweck des Threads ist es ja nicht nur die Progressbar aus diesem upzudaten, sondern in diesem die Aufgabe ablaufen zu lassen die erledigt werden soll und gleichzeitig daraus die Progressbar upzudaten.

Irgendwie hast du da noch einen Knoten im Hirn.

Das Thema ist leider etwas komplexer aber da musst du durch wenn du das damit lösen willst. Aller Anfang ist schwer, da hilft nur Doku lesen und Debugging.

Viel Erfolg weiterhin
Gruß grexit
Bitte warten ..
Mitglied: derhoeppi
18.10.2015 um 19:55 Uhr
Hallo grexit,

derzeit werden es immer mehr Knoten im Kopf.
Ich habe mir im Internet nun nochmals mehrere Beiträge / Artikel angesehen um das Thema Runspace zu verstehen. Die Beispiele die gefunden habe, sind allerdings wenig hilfreich, weil eben genau das Verhalten der Progressbar oder das befüllen irgendwelcher TextBoxen direkt im Scriptblock stattfindet. An und für sich ist das auch in Ordnung und korrekt. Nach deinem zweiten Beitrag bin ich jedoch etwas verwirrt. Du hast geschrieben das "$syncHash.value = $Progress" unnötig ist. Wenn ich jedoch den fertigen Wert ($Progress = Value) in die Hashtabelle schreibe, muss ich diesen doch nicht darin berechnen lassen.

Ich habe soeben meine komplette GUI in einem Runspace laufen lassen. Somit war ich aus meinem Hauptthread in der Lage die Progressbar zu aktualisieren. Mit dem Starten der GUI in einem separaten Thread habe ich nun aber ein anderes Problem. Die GUI Objekte (Button, ListViews, Textboxen) liegen nun in einem anderen Thread. Wie kann ich denen Aktionen, wie zum Beispiel ein OnClick für einen Button hinzufügen, der wiederum in meinem Haupt-Thread ablaufen soll. Ich habe ebenfalls die Hashtabelle erzeugt in der alle WPF Elemente liegen. Diese kann ich ansprechen und Eigenschaften verändern. Wenn ich jedoch in meiner GUI ein Event z.B. ein Button_onClick durchführe, möchte ich das dies im Hauptthread ausgeführt wird.

Dann habe ich noch eine andere Frage. Bei dem Versuch meine GUI in dem SubThread laufen zu lassen, konnte ich ohne Probleme die Hashtabelle abfragen. Wie aber kann ich genau das realisieren, wenn die GUI in meinem Haupthread läuft und die Eingaben blockiert sind. Muss ich mit einer Textausgabe oder Messagebox arbeiten oder wie kann ich das Troubleshooten?

Gruß
derhoeppi
Bitte warten ..
Mitglied: derhoeppi
19.10.2015, aktualisiert um 08:24 Uhr
Guten Morgen,

das Thema wurmt mich . Wenn ich die GUI in einen separaten Thread auslagere, kann ich die Progressbar verändern. Wenn ich die GUI im Hauptthread laufen lasse, schaffe ich es nicht diese über einen SubThread zu verändern. Ich habe mir nun im SubThread eine Messagebox erstellt, in der ich die Werte von $syncHash.value ausgeben lasse. Die Messagebox meldet mir brav den Wert, der im Hauptthread in die Hashtabelle geschrieben wurde. Nach dem Ende des Skriptes schaue ich mir mit $syncHash den Inhalt der Hashtabelle an. Dort sehe ich genau die Objekte, die ich der Tabelle hinzugefügt habe.
Darin habe ich bis jetzt mein GUI-Window, den Fortschrittswert, die Progressbar und zum Test noch eine Checkbox. Und obwohl ich die Progressbar und die Checkbox in der Hashtabelle habe, kann ich deren Werte nicht abfragen. Einzig auf den Fortschrittswert habe ich Zugriff und kann ihn auslesen. Verändern darf ich aber auch diesen nicht! An diesem Punkt kommen mir Zweifel. Mit Hilfe der Hashtabelle soll es doch möglich sein Werte aus mehreren Thread lesen und bearbeiten zu können. Warum funktioniert das dann nicht?

01.
#Folgende Zeilen stehen global im Skript und nicht verschachtelt
02.
$script:syncHash = [hashtable]::Synchronized(@{})
03.
$script:newRunspace =[runspacefactory]::CreateRunspace()
04.
$script:newRunspace.ApartmentState = "STA"
05.
$script:newRunspace.ThreadOptions = "ReuseThread"         
06.
$script:newRunspace.Open()
07.
$script:newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)     
08.

09.
# Funktion zum Errechnen des Fortschritt in der Statusbar
10.
Function Statusbar{
11.
    $ChB_checkedCount = 0
12.
    $ChB_disabledCount = 0      
13.
           
14.
            if($ChB_1.IsChecked -eq $true){
15.
               $ChB_checkedCount = $ChB_checkedCount +1
16.
               if($ChB_1.IsEnabled -eq $false){
17.
                   $ChB_disabledCount = $ChB_disabledCount +1
18.
                    }
19.
                }
20.
            if($ChB_2.IsChecked -eq $true){
21.
               $ChB_checkedCount = $ChB_checkedCount +1
22.
               if($ChB_2.IsEnabled -eq $false){
23.
                    $ChB_disabledCount = $ChB_disabledCount +1
24.
                    }
25.
                }
26.
               $ProgressBase = 100 / $ChB_checkedCount
27.
    [int]$Progress = $ProgressBase * $ChB_disabledCount
28.
    write-host $Progress
29.
    $script:syncHash.progress = $PB_Status #PB_Status ist meine Progressbar
30.
    $script:syncHash.value = $Progress
31.
    $psCmd = [PowerShell]::Create().AddScript({   
32.
        $script:syncHash.progress.Value = $script:syncHash.value
33.
        [System.Windows.Forms.MessageBox]::Show($script:syncHash.value,"Fortschritt",0,[System.Windows.Forms.MessageBoxIcon]::Information)
34.
    
35.
    })
36.
    $psCmd.Runspace = $script:newRunspace
37.
    $data = $psCmd.BeginInvoke()
38.
}
Sorry wenn ich damit nerve, aber ich möchte es nur verstehen.

Gruß
derhoeppi
Bitte warten ..
Mitglied: 122990
19.10.2015, aktualisiert um 09:18 Uhr
Da sind wieder einige Dinge falsch, erstens brauchst du $syncHash.value nicht da du die ganze Progressbar schon einer Hashtable-Property zugewiesen hast, und du den Progressvalue Wert damit live verändern kannst !!!
Zweitens greifst du falsch auf die Hashtable im SubThread zu ($script:syncHash), das ist nicht korrekt weil hiermit
$script:newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
eine extra Variable, welche ebenfalls "syncHash" heißt, für den Zugriff im SubThread erzeugt wird.
Deswegen musst du auch über diese aus dem SubThread drauf zugreifen. $syncHash.progress.value = XX

Der zweite Thread ist ja dazu da das wir im ersten nicht mit einer Schleife warten müssen, denn das würde die GUI ja unresponsive machen!

Das es einwandfrei klappt siehst du ja an @colinardo 's Beispiel, du setzt es nur nicht richtig um.

Und das mit der GUI im SubThread, vergess es, als Anfänger ist das zu komplex. Dazu solltest du erst mal mit c# oder Vb.net Threading-Programme programmieren und üben, damit du das Threading-Konzept erst mal grundlegend verstehst, sonst wird das nie was.
Bitte warten ..
Mitglied: derhoeppi
19.10.2015 um 10:26 Uhr
Zitat von 122990:

Da sind wieder einige Dinge falsch, erstens brauchst du $syncHash.value nicht da du die ganze Progressbar schon einer Hashtable-Property zugewiesen hast, und du den Progressvalue Wert damit live verändern kannst !!!
>...
Und das mit der GUI im SubThread, vergess es, als Anfänger ist das zu komplex. Dazu solltest du erst mal mit c# oder Vb.net Threading-Programme programmieren und üben, damit du das Threading-Konzept erst mal grundlegend verstehst, sonst wird das nie was.

Hallo Grexit,

die GUI im SubThread habe ich eigentlich nur zum Verständnis erzeugt. Als das funktionierte, habe ich mich gefreut überhaupt etwas aus einem anderen Thread an der GUI zu verändern. Die GUI im SubThread zu belassen ist nicht meine Intention, aber dadurch das ich von außen auf den Thread zugreifen kann, ist das Troubleshooting "einfacher".
Den Part mit $syncHash.value muss ich leider aufgreifen, weil ich das Gefühl habe, dass ich Dich entweder komplett falsch verstehe oder wir aneinander vorbei reden. $syncHash.value beinhaltet einen Integer Wert, den ich der Progressbar als Value zuweisen möchte. $syncHash.value berechne ich aus den Checkboxen.

Um wenigstens eine einfache Funktion sicherzustellen, habe ich nun in meiner Skriptanweisung folgendes zu stehen: $syncHash.progress.value = 12
Leider passiert in der GUI nichts. Wenn ich jedoch den Runspace richtig initialisiert habe, und den Runspace mit dem Skript aufrufe - warum passiert nichts?

Gruß
derhoeppi
Bitte warten ..
Mitglied: 122990
19.10.2015, aktualisiert um 10:47 Uhr
Zitat von derhoeppi:
$syncHash.value beinhaltet einen Integer Wert, den ich der Progressbar als Value zuweisen möchte.
Eben das geht nicht, weil das nicht automatisch der Progressbar zugewiesen wird, im Gegensatz zu dem ganzen Progressbar-Objekt mit welchem sich automatisch der Wert der Progressbar setzen lässt

Um wenigstens eine einfache Funktion sicherzustellen, habe ich nun in meiner Skriptanweisung folgendes zu stehen: $syncHash.progress.value = 12
Leider passiert in der GUI nichts. Wenn ich jedoch den Runspace richtig initialisiert habe, und den Runspace mit dem Skript aufrufe - warum passiert nichts?

Läuft denn das Beispiel von Colinardo bei dir überhaupt ? Geht hier einwandfrei ..
Bitte warten ..
Mitglied: derhoeppi
19.10.2015 um 11:38 Uhr
Hallo,

das Beispiel (im Beitrag "Powershell progressbar AND multitask") mit dem Timer von Uwe läuft bei mir einwandfrei. In dem Zuge wird aber nicht mit Runspaces gearbeitet, so dass es schwer fällt dieses Beispiel in meinen Fall zu übertragen. Der Timer hört in Uwes Skript nur beim Betätigen des Buttons auf zu laufen. Bei mir soll das Skript einfach durchlaufen und nach Abschluss einer Funktion die Progressbar aktualisieren.

Nun nochmal zum $syncHash.value. Ich nehme sowohl diesen Wert als auch die Progressbar unabhängig voneinander über die Hashtabelle mit in den SubThread. Dort nehme ich dann die Zuweisung manuell vor. Das muss doch gehen oder? Es ist doch letztlich nichts anderes als eine Variablenzuweisung.

Gruß
derhoeppi
Bitte warten ..
Mitglied: 122990
19.10.2015, aktualisiert um 11:42 Uhr
Ich meinte den zweiten Link
https://www.administrator.de/forum/powershell-gui-bleibt-schleife-hä ...
Dort werden sehr wohl RunSpaces eingesetzt!
Das muss doch gehen oder?
Klar.
Nur wird eben der Wert für die Progressbar nur "automatisch" von der GUI übernommen wenn du es über das Progressbar-Objekt machst.
Bitte warten ..
Mitglied: derhoeppi
19.10.2015 um 12:47 Uhr
Hallo grexit,
bevor ich mir das zweite Beispiel noch einmal genauer ansehe. Ich habe jetzt in dem $psCmd Script eine For-Schleife eingebaut, die von 1 bis 100 zählt und diesen Wert an die Statusbar weitergibt. Leider verändert sich in meiner Progressbar gar nichts. Ich muss also ein Problem beim Ansprechen der Progressbar haben.

Gruß
derhoeppi
Bitte warten ..
Mitglied: derhoeppi
19.10.2015, aktualisiert um 20:42 Uhr
Hi,

ich habe nun noch einmal von 0 angefangen. Dazu habe ich mir eine XAML Datei erstellt, die mein Frontend enthält. Diese spreche ich aus der ps1 Datei an. Hier mein Code:

Code der ps1
01.
 #Dll einbinden 
02.

03.
	Add-Type -AssemblyName PresentationFramework
04.
	Add-Type -AssemblyName System
05.
    [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
06.

07.
# Einbinden der Windows Form XAML Datei
08.
	[XML]$XAML = Get-Content -Path "C:\Scripts\Statusbar\MainWindow.xaml"
09.
	$XAML.Window.RemoveAttribute("x:Class")
10.
	$Reader = New-Object System.Xml.XmlNodeReader $XAML
11.
	$Form = [Windows.Markup.XAMLReader]::Load($Reader)
12.

13.
$Btn_Close_Click = ({Beenden})
14.
$Btn_Start_Click = ({Main})
15.

16.
#Create synchronized Hashtable-Object for communication between sub-thread and form
17.
$syncHash = [hashtable]::Synchronized(@{})
18.
# initialize second Powershell runspace
19.
$psCmd = [powershell]::Create()
20.

21.
Function GenerateForm {
22.
    $Btn_Close = $Form.FindName('Btn_Close')
23.
    $Btn_Start = $Form.FindName('Btn_Start')
24.
	$ChB_Test = $Form.FindName('ChB_Test')
25.
	$PB_Status = $Form.FindName('PB_Status')
26.
    $Btn_Close.Add_Click($Btn_Close_Click)
27.
	$Btn_Start.Add_Click($Btn_Start_Click)
28.
    $PB_Status.Value = 0
29.
	#set the controls in the hashtable we wish to manipulate
30.
    $syncHash.Status = $PB_Status
31.

32.

33.
    $async = $Form.Dispatcher.InvokeAsync({$Form.ShowDialog() | Out-Null})
34.
    $async.Wait() | Out-Null
35.
    }
36.

37.
Function Beenden{
38.
$Form.Close()
39.
}
40.

41.
Function Main{
42.
    # create new runspace to run our sub-thread in
43.
    
44.
    $newRunspace =[runspacefactory]::CreateRunspace()
45.
    $newRunspace.ApartmentState = "STA"
46.
    $newRunspace.ThreadOptions = "ReuseThread"          
47.
    $newRunspace.Open()
48.
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
49.

50.
    $psCmd.AddScript({
51.
                          # in this expample we set the progress-bar value every 500 ms
52.
                          for ($i = 1;$i -le 10;$i++){
53.
                              sleep -Milliseconds 500
54.
                              $syncHash.Status.Value = $i * 10
55.
                              [System.Windows.Forms.MessageBox]::Show($i,"Aufruf Deploy Skript",0,[System.Windows.Forms.MessageBoxIcon]::Information)
56.
                          }
57.
                     })
58.
    $psCmd.Runspace = $newRunspace
59.
    #start the runspace
60.
    $data = $psCmd.BeginInvoke()
61.

62.
}
63.

64.
GenerateForm
Code der XAML
01.
<Window x:Name="Form" x:Class="Multithreading.MainWindow"
02.
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
03.
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
04.
        Title="MainWindow" Height="180" Width="525">
05.
    <Grid>
06.
        <Button x:Name="Btn_Start" Content="Start" Margin="340,113,102,0" VerticalAlignment="Top"/>
07.
        <ProgressBar x:Name="PB_Status" HorizontalAlignment="Left" Height="30" Margin="64,43,0,0" VerticalAlignment="Top" Width="219"/>
08.
        <CheckBox x:Name="ChB_Test" Content="CheckBox" HorizontalAlignment="Left" Margin="340,71,0,0" VerticalAlignment="Top"/>
09.
        <Button x:Name="Btn_Close" Content="Beenden" HorizontalAlignment="Left" Margin="432,113,0,0" VerticalAlignment="Top" Width="75"/>
10.

11.
    </Grid>
12.
</Window>
Nachdem ich diese beiden Dateien erzeugt habe, dachte ich wird es funktionieren. Ich habe lediglich die XAML Datei erzeugt und anschließend den Code aus Uwe's Beispiel eingefügt. Die Progressbar wird aber nicht angesprochen, obwohl ich sie im $syncHash nach der Skriptlauzeit finde. Es scheint mir so als hätte ich ein trivaleres Problem. Den SubThread arbeitet er zwar ab, aber er kann aus dem SubThread nicht meine Progressbar ansprechen.

Gruß
derhoeppi
Bitte warten ..
Mitglied: 122990
LÖSUNG 19.10.2015, aktualisiert um 21:15 Uhr
Ist ja auch ein Unterschied zwischen Tag und Nacht @colinardo verwendet im Beispiel Windows Forms nicht WFP, das sind zwei ganz unterschiedliche Schuhe ...
Zu WPf müsste ich erst nochmal nachsehen wie dort die Progressbar angesprochen werden muss.
Bitte warten ..
Mitglied: derhoeppi
19.10.2015 um 21:15 Uhr
Hallo grexit,

so ich habe nun die Lösung . Für das ansprechen der WPF Elemente muss ich mit der Methode Invoke() arbeiten. Als Fazit sieht meine for-Schleife nun so aus:

01.
for ($i = 1;$i -le 10;$i++){
02.
                              sleep -Milliseconds 500
03.
                              #$syncHash.Status.Value = 10
04.
                              $syncHash.Status.Dispatcher.Invoke("Normal", [action]{
05.
        $syncHash.Status.Value=$i *10})
06.
}
So und nun kann ich endlich weitermachen. Danke für den Hinweis das ich wieder einmal nicht nach WPF Beispielen, sondern Windows Forms gesehen habe.

Gruß
derhoeppi
Bitte warten ..
Mitglied: derhoeppi
20.10.2015 um 10:02 Uhr
Hallo,
ich muss das Thema noch einmal hochholen. Nachdem ich gestern einen Aha Effekt hatte und mich über den Fortschritt gefreut habe, habe ich heute morgen versucht, den Code in mein bestehendes Skript zu integrieren. Daran bin ich gescheitert und bin deshalb zu dem obigen Beispiel zurückgekehrt. Ich habe das Beispiel um eine Funktion erweitert.
Folgendes wollte ich erreichen. Beim Klick auf den Button Start, soll die Funktion Main aufgerufen werden. In der Funktion Main gibt es eine For-Schleife, die drei Mal durchlaufen soll. In der For-Schleife wird die Funktion Statusbar aufgerufen, die zur Aufgabe hat, die Progressbar von 0-100% zu füllen.
Bei zwei von drei Durchläufen erhalte ich folgende Fehlermeldungen:
1. Exception calling "AddScript" with "1" argument(s): "The state of the current PowerShell instance is not valid for this operation."
2. Exception setting "Runspace": "The state of the current PowerShell instance is not valid for this operation."
3. Exception calling "BeginInvoke" with "0" argument(s): "The operation cannot be performed because a command has already been started. Wait for the command to complete, or stop it, and then try the operation again."

Derzeitiger Code:
01.
#Dll einbinden 
02.

03.
	Add-Type -AssemblyName PresentationFramework
04.
	Add-Type -AssemblyName System
05.
    [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
06.

07.
# Einbinden der Windows Form XAML Datei
08.
	[XML]$XAML = Get-Content -Path "C:\Scripts\Statusbar\MainWindow2.xaml"
09.
	$XAML.Window.RemoveAttribute("x:Class")
10.
	$Reader = New-Object System.Xml.XmlNodeReader $XAML
11.
	$Form = [Windows.Markup.XAMLReader]::Load($Reader)
12.

13.
$Btn_Close_Click = ({Beenden})
14.
$Btn_Start_Click = ({Main})
15.

16.
#Create synchronized Hashtable-Object for communication between sub-thread and form
17.
$syncHash = [hashtable]::Synchronized(@{})
18.
#set the controls in the hashtable we wish to manipulate
19.
    
20.
# initialize second Powershell runspace
21.
$psCmd = [powershell]::Create()
22.

23.
Function GenerateForm {
24.
    $Btn_Close = $Form.FindName('Btn_Close')
25.
    $Btn_Start = $Form.FindName('Btn_Start')
26.
	$ChB_Test = $Form.FindName('ChB_test')
27.
	$PB_Status = $Form.FindName('PB_Status')
28.
    $Btn_Close.Add_Click($Btn_Close_Click)
29.
	$Btn_Start.Add_Click($Btn_Start_Click)
30.
    $PB_Status.Value = 0
31.
    $syncHash.Status = $PB_Status
32.

33.

34.
    $async = $Form.Dispatcher.InvokeAsync({$Form.ShowDialog() | Out-Null})
35.
    $async.Wait() | Out-Null
36.
    }
37.

38.
Function Beenden{
39.
$Form.Close()
40.
}
41.

42.
Function Statusbar{
43.
    # create new runspace to run our sub-thread in
44.
    
45.
    $newRunspace =[runspacefactory]::CreateRunspace()
46.
    $newRunspace.ApartmentState = "STA"
47.
    $newRunspace.ThreadOptions = "ReuseThread"          
48.
    $newRunspace.Open()
49.
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
50.

51.
    $psCmd.AddScript({
52.
                          for ($i = 1;$i -le 10;$i++){
53.
                              sleep -Milliseconds 100
54.
                              $syncHash.Status.Dispatcher.Invoke([action]{$syncHash.Status.Value= $i * 10},"Normal")
55.
                          }
56.
                     })
57.
    $psCmd.Runspace = $newRunspace
58.
    #start the runspace
59.
    $data = $psCmd.BeginInvoke()
60.
    sleep -Seconds 5
61.
}
62.

63.
Function Main{
64.
    for ($k = 1;$k -le 3;$k++){
65.
    Statusbar
66.
    sleep -Seconds 5
67.
    $newRunspace.Dispose()
68.
    }
69.
}
70.

71.
GenerateForm
72.
$newRunspace.Close()
Woran könnte mein Problem liegen. Aufgrund der Fehlermeldung 3 habe ich die Zeit in Vermutung. Aber selbst Ruhezeiten habe es nicht verbessert.

Gruß
derhoeppi
Bitte warten ..
Ähnliche Inhalte
Batch & Shell

Powershell: Elemente der WPF-GUI beim ersten starten updaten

gelöst Frage von clubmateBatch & Shell8 Kommentare

Hallo Freunde, ich denke das ist eher was für die Powershell-Cracks: Ich habe ein Programm geschrieben welches ein Inkrementelles ...

Batch & Shell

PowerShell WPF TabControl

Frage von derhoeppiBatch & Shell1 Kommentar

Hallo, in einer GUI (WPF) habe ich ein Ereignis auf einem TabControl. Das Ereignis nennt sich SelectionChanged. Nun habe ...

Batch & Shell

Powershell Neustart GUI

gelöst Frage von 136430Batch & Shell9 Kommentare

Hallo ich möchte in einer GUI einem User einen Neustart eines Remotecomputers zur Verfügung stellen, der user führt das ...

Batch & Shell

Powershell ListView DataGrid in WPF

gelöst Frage von derhoeppiBatch & Shell7 Kommentare

Hallo, ich habe in einer xaml Datei ein ListView Element erstellt. Die xaml Datei wird durch das PowerShell Skript ...

Neue Wissensbeiträge
Voice over IP

Telekom Umstellung von ISDN Anlagenanschluss auf IP-Telefonie

Erfahrungsbericht von NixVerstehen vor 3 TagenVoice over IP7 Kommentare

Hallo zusammen, nachdem nun vor ein paar Tagen die zwangsweise Umstellung von ISDN auf IP-Telefonie problemlos über die Bühne ...

Apple

Apple Special Event vom 10.09.2019: Arcade, TV+, iPad und iPadOS, Watch und iPhone 11

Information von Trontur vor 4 TagenApple2 Kommentare

Hier könnt ihr euch die Keynote von Tim Cook auf dem Apple Special Event vom 10.09.2019 anschauen: September Event ...

LAN, WAN, Wireless

Das RIPE ist quasi endgültig leer was IPv4 angeht

Information von LordGurke vor 12 TagenLAN, WAN, Wireless8 Kommentare

Das RIPE teilt mit, dass sie erwarten, Ende des Jahres keine /22-IPv4-Allocations (1.024 Adressen) mehr vergeben zu können. Dann ...

Verschlüsselung & Zertifikate

Ein besserer Weg zur Delegation of Control für Bitlocker Recoverykeys

Anleitung von DerWoWusste vor 12 TagenVerschlüsselung & Zertifikate

Will man Supportmitarbeitern ermöglichen, Bitlocker-Recoverykeys auszulesen, dann bietet sich eigentlich der Delegation of Control Wizard an. Ich zeige zunächst ...

Heiß diskutierte Inhalte
Windows Server
Drucker auf dem Terminalserver 2016 via Printserver wird nicht angezeigt
Frage von EchterHansenWindows Server14 Kommentare

Moin Moin, ich habe hier zwei 2016er Terminalserver und einen 2016er Printserver, auf dem ca. 10 RICOH-Drucker Typ 4. ...

Hardware
Ncomputing N600 oder auch 600W Privat nutzen Kostenlos oder kostengünstig
gelöst Frage von PlerTanixHardware13 Kommentare

Hallo liebe Forum User, Ich habe da eine Frage. Ich bin Azubi im dritten Lehrjahr und bei uns in ...

Windows 10
Upgrade Windows 10 1903 und Office 2010 Problem mit Userzertifikaten
gelöst Frage von Looser27Windows 1012 Kommentare

Guten Morgen, ich habe bei uns ein Phänomen in o.g. Kombination festgestellt, welches nach dem Inplace-Upgrade auf 1903 auftritt. ...

Hardware
Ausrichtung Profilschienen - was würdet ihr empfehlen?
gelöst Frage von ShihanHardware10 Kommentare

Ich habe einen Digitus 19" 12 U Netzwerkschrank. Dieser hätte eigentlich nur vorne Profilschienen, da ich aber im hinteren ...