PowerShell GUI WPF
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
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
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-Key: 285511
Url: https://administrator.de/contentid/285511
Ausgedruckt am: 29.03.2024 um 00:03 Uhr
18 Kommentare
Neuester Kommentar
Moin,
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
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
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.
für 50 Prozent.
In deinem Teil oben machst du einige Fehler wie z.B. das hier hat keinen Nutzen:
denn du hast ja schon eine Eigenschaft der Hashtable hiermit übergeben:
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
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.
$syncHash.progress.Value = 50
In deinem Teil oben machst du einige Fehler wie z.B. das hier hat keinen Nutzen:
$syncHash.value = $Progress
$syncHash.progress = $PB_Status
Das ist die ganze Magie dahinter.
Gruß grexit
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
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
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
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.
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.
Zweitens greifst du falsch auf die Hashtable im SubThread zu ($script:syncHash), das ist nicht korrekt weil hiermit
$script:newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
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.
$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
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 ..Leider passiert in der GUI nichts. Wenn ich jedoch den Runspace richtig initialisiert habe, und den Runspace mit dem Skript aufrufe - warum passiert nichts?
Ich meinte den zweiten Link
Powershell GUI bleibt während einer While schleife hängen...
Dort werden sehr wohl RunSpaces eingesetzt!
Nur wird eben der Wert für die Progressbar nur "automatisch" von der GUI übernommen wenn du es über das Progressbar-Objekt machst.
Powershell GUI bleibt während einer While schleife hängen...
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.
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.
Zu WPf müsste ich erst nochmal nachsehen wie dort die Progressbar angesprochen werden muss.