none
Programme aufrufen und in Textbox darstellen RRS feed

  • Frage

  • Hallo

    Seit kurzem verusche ich in der powershell kleine Helferprogramme zu schreiben, welche einfache Kommandozeilen-Programme in eine gui packen. Ziel ist es, dass die Anwender nicht mehr Programme mit ganz vielen Kommandozeilen-Parametern angeben müssen, sondern die gui aufrufen, Programm starten und die normale Cmd-Ausgabe wird in einer einfachen Textbox dargestellt.Die Programme sind allesamt cmd-Programme (teils ältere Cobol-Programme) aus einer Anwendungssammlung. Die gibt es leider nicht mit ner gui und haben eine Menge stets ähnlicher Optionen. Die Ausgabe erfolgt dabei Zeichen für Zeichen ( wie z.B. ein ASCII-Fortschrittsbalken) und nicht immer als ganze Zeilen, wie im Script unten mit ping angegeben.

    Ich habe dies auch schon so ungefähr hinbekommen, bin aber mit meiner Implementierung nicht zufrieden:

    $rswReorgByDirStartReorgButton_OnClick=
    {
        $rswReorgByDirOutput.AppendText("---------------------------------`r`n")
        $rswReorgByDirOutput.AppendText("Starting Output:`r`n")
        $rswReorgByDirReorgJob = Start-Job {
            ping -n 100 127.0.0.1
        }
        do {
            # get new results, add them to old ones, and output them
            # @() required to make sure PowerShell knows it is a collection
            $results = @(Receive-Job $rswReorgByDirReorgJob) -join "`r`n"
            #$results -join "`r`n"
            $rswReorgByDirOutput.AppendText($results + "`r`n")
            
            Start-Sleep -Milliseconds 500
        } while ( $rswReorgByDirReorgJob.JobStateInfo.State -ne 'Completed' )
        $rswReorgByDirOutput.AppendText("Ending Output:`r`n")
        $rswReorgByDirOutput.AppendText("---------------------------------`r`n")
    
    }

    Das Problem ist, dass die angegebenen Befehle die gui komplett blockieren, bis das Programm zu Ende ausgeführt ist. Dies ist ziemlich blöd, da die Programme auch mal gerne 20-60min laufen können. Zudem ist die Ausgabe mit den Zeilenumbrüchen nicht akzeptabel und unterscheidet sich von der normalen Befehlsausgabe. Ich denke, dass kann man besser machen. Optimal wäre, wenn die Ausgabe in der Textbox sich nicht von der Ausgabe in einer cmd unterscheidet. Hatte bereits im Internet nach Lösungen gesucht, bin aber einen Hinweis, wie ich so etwas aufbauen kann, habe ich noch nicht gefunden. Vielleicht suche ich ja immer nach den falschen Stichwörtern...

    Jemand eine Idee, wie ich an so etwas herangehen kann??

    Samstag, 30. Juni 2012 20:41

Antworten

  • Den Ansatz mit DoEvents habe ich die doch gepostet !

    >> Brauchst also nicht ganz so weit auszuholen.
    Ok ! Ich versuche so zu schreiben, dass alle die hier mitlesen auch was verstehen (könnten) ;-)).

    PowerShell und GUI ist ein spannendes Thema.
    Man muss immer bedenken dass PowerShell eine Skript Engine ist und da wird’s dann irgendwann eng mit den Themen Mutithreading oder GUI.
    In Skripts sollte man halt nur kleinere GUI Elemente wie Inputbox und Messagebox nutzen. Dies geht ja mit Windows Forms sehr leicht.
    Alles andere sollte dann am besten, eine Programmierte Applikation werden, die eine PowerShell hostet, um PowerShell befehle auszuführen. Da kommt man um das „echte Programmieren“ nicht herum denke ich.

    Ich habe mich bisher auf kleine GUIs beschränkt, die einen User Input verarbeiten, deshalb habe ich mich mit dem Thema „Oberfläche friert ein“ noch nicht beschäftigt.

    Es gab mal für PowerShell die beiden WPF basierten Ansätze PowerBoots und Microsoft PowerShell Power Pack (WPK) diese hatten die Möglichkeit die GUI als Job zu starten.
    Die Entwickler von WPK und PowerBoots haben sich zusammengetan und haben ein neues PowerShell WPF Produkt entwickelt das nennt sich PowerShell ShowUI:
    http://showui.codeplex.com/
    http://huddledmasses.org/showui-tutorial-walkthrough/
    http://show-ui.com/?Walkthru=Getting%20started%20with%20ShowUI

    Für Show UI und WPF gibt es auch einen Online Designer:
    http://www.poshboard.com/Designer/Default.html

    PowerShell startet normalerweise im Multithread Apartment Modus (MTA), WPF braucht aber den Single Thread Apartment (STA)  Modus deshalb wird hier schon etwas schwierig.
    (Einige Windows Forms laufen mit dem STA auch besser)

    Aber nochmal zu 2.)
    Um einen neuen Thread vom Prozess abzuspalten war schon unter Visual Basic 6 der Timer sehr beliebt:
    http://www.reddit.com/r/PowerShell/comments/s74rf/avoiding_gui_lockup_when_running_a_command_eg_a/

    Anstatt des Background Workers empfiehlt der MVP Keith Hill Register-ObjectEvent  zu nutzen:
    http://stackoverflow.com/questions/3969793/powershell-backgroundworker


    Please click “Mark as Answer” if my post answers your question and click Vote as Help if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als Hilfreich und Beiträge die deine Frage ganz oder teilweise beantwortet haben als Antwort.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '


    Montag, 2. Juli 2012 09:05

Alle Antworten

  •  

    Hallo  dspringer_rsw,

    Willkommen im PowerShell Forum.

    1.)

    Zum Erstellen von Grafischen Benutzeroberflächen (GUI) mit der PowerShell PowerShell gibt es mehrere Wege.
    Man kann die im .NET Framework enthaltenen Techniken Windows Forms (WinForms) oder Windows Presentation Foundation (WPF) nutzen. Ebenso kann man den Internet Explorer dazu missbrauchen (nicht empfohlen!).
    Ich empfehle immer Windows Forms zu nutzen da dies mit PowerShell am einfachsten ist.

    Denniver Reining (Moderator diese Forums) hat auf seinem Blog eine gute Einführung dazu geschrieben (leider in English).
    http://bytecookie.wordpress.com/2011/07/17/gui-creation-with-powershell-the-basics/

    Da das Erstellen von GUI mit der „Hand“ schnell langweilig wird und viel Zeit kostet  (z.B. Position jedes Elementes festlegen). Hat die Firma Sapien für PowerShell eine Entwicklungsumgebung erstellt mit der man sich eine GUI „zusammenklicken kann“ die nennt sich  Sapien PrimalForms Community Edition und ist kostenlos.
    Wie man damit GUI erstellt habe ich in meinem Video auf Youtube erklärt:  
    www.youtube.com/watch?v=y76LO5VIN24

    2.)

    PowerShell führt all seine Arbeit im selben Prozess aus deshalb kann PowerShell nicht mehr auf GUI Ereignissen (Events) reagieren wenn der Prozess mit Rechnen (Arbeiten) beschäftig ist.
    Hier benötigt man so genanntes Multithreading (ein Prozess hat mehrere Handlungsstränge die „gleichzeitig“ arbeiten).
    Dr. Tobias Weltner (ein deutscher) hat dazu ein englischen Webcast :
    http://www.idera.com/Events/RegisterWC.aspx?EventID=297

    Man kann das auch teilweise umgehen in dem man in einer Schleife die Arbeit erledigt und DoEvents aufruft.
    Das ist aber nicht sehr sauber und die Events kommen da nicht immer durch!
    http://stackoverflow.com/questions/10794455/powershell-freezing-gui

    3.)

    Eine Output Funktion die in der Konsole und in einer GUI gleichermaßen ausgaben anzeigt (Hybrid) ist nicht unmöglich.
    Ich selbst habe so etwas schon Programmiert.
    Dies ist aber auf einfache Messagebox Funktionalität beschränkt, man kann halt nicht jede mögliche Ausgabe vorhersehen und Hybrid zur Verfügung stellen.
    Dazu müsste man den PowerShell Host abfragen (Läuft das Skript in der Konsole? Dann Konsolen Ausgabe) oder anhand eines Parameter GUI=1 oder man Programmiert sich seinen eigenen PowerShell Host.

    --------------------------------------------------

    Als alternative würde ich vorschlagen deine ausgaben in der PowerShell Konsole zu machen und die Usereingaben auch dort abzufragen.
    Man kann auch in der PowerShell Konsole Menues Programmieren.
    http://jdhitsolutions.com/blog/2011/12/friday-fun-a-powershell-console-menu/
    http://poshtips.com/2011/09/03/howto-make-menus-in-powershell/

    Fast dasselbe, erreichst du mit Advanced Functions und Mandatory Parameter.


    Please click “Mark as Answer” if my post answers your question and click Vote as Help if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als Hilfreich und Beiträge die deine Frage ganz oder teilweise beantwortet haben als Antwort.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '


    Montag, 2. Juli 2012 06:18
  • Danke für die Antwort Peter.

    Da du dir sehr viel Mühe gibst mir Grundlagen verständlich zu vermitteln nur kurz die Info, dass ich seit knapp 10 Jahren als Admin in einer Firma tätig bin. Brauchst also nicht ganz so weit auszuholen. Multithreading kenn ich. Habe auch einige Erfahrung in der Linux-Shell-Programmierung, aber Windows (insbesondere GUI) ist für mich neu.

    Zu 1) Ich habe bereits einiges gelesen, wie ich in der Powershell eine Gui erstelle. Bin dann auch schliesslich auf PrimalForms ausgekommen. Nehme dieses Tool jetzt auch als Basis für die entwicklung. Aber Danke für den Hinweis.

    zu 2) In meinen Recherchen hatte ich viele ähnliche Programme gefunden, aber eigentlich hatten alle ein Problem, dass bei der Befehlsausführung im Hintergrund die gui selbst einfriert. Werde wohl mal mit der DoEvents-Schleife experimentieren. In Beispielen zu anderen .net-Programmiersprachen habe ich teilweise Lösungen mit einem Background-Worker gefunden. Diese konnte ich aber nie umsetzen. Da ich mein Problem aber als sehr grundsätzlich eingestuft hatte, habe ich ermutet, dass es hier so etwas wie einen Königsweg gibt und ich nur falsch suche. Grundsätzlich will ich nur via gui ein Consolen-Programm konfigurieren, dann starten und die Ausgabe in der Gui darstellen. Ob dies jetzt in der gleichen Instanz der Powershell ausgeführt wird, oder einfach ein neuer Prozess gestartet wird, ist mir dabei eigentlich egal, hauptsache die Ausgabe stimmt.

    zu 3) Mir geht es insbesondere darum alte bestehende Consolen-Programme aufzuwerten. Consolen-Menüs haben wir auf cygwin-Basis auch schon seit langer Zeit umgesetzt, aber die will ich loswerden. Der Umstieg auf die Powershell-consolen-Menüs wäre daher in diesem Fall nicht lohnend. Die Consolen-Ausgabe ist mir da der Befehlsausführung nicht wichtig, sondern lediglich die GUI-Darstellung. Diese soll sich dann aber möglichst nicht unterscheiden von dem, was eigentlich auf der Console angezeigt wird. Naja, zusätzliches Logging in ein Protokoll wäre noch schön, aber dazu habe ich auch schon mal Besipiele gefunden. Wäre was für später einmal...

     

    Montag, 2. Juli 2012 07:08
  • Nachtrag:

    Einen weiteren Ansatz bzgl. des Freezing konnte ich nun selbst noch finden.

    Der Aufruf von [System.Windows.Forms.Application]::DoEvents() innerhalb der angegebenen do-while-Schleife erhält die Bedienbarkeit der Gui.

    Montag, 2. Juli 2012 08:48
  • Den Ansatz mit DoEvents habe ich die doch gepostet !

    >> Brauchst also nicht ganz so weit auszuholen.
    Ok ! Ich versuche so zu schreiben, dass alle die hier mitlesen auch was verstehen (könnten) ;-)).

    PowerShell und GUI ist ein spannendes Thema.
    Man muss immer bedenken dass PowerShell eine Skript Engine ist und da wird’s dann irgendwann eng mit den Themen Mutithreading oder GUI.
    In Skripts sollte man halt nur kleinere GUI Elemente wie Inputbox und Messagebox nutzen. Dies geht ja mit Windows Forms sehr leicht.
    Alles andere sollte dann am besten, eine Programmierte Applikation werden, die eine PowerShell hostet, um PowerShell befehle auszuführen. Da kommt man um das „echte Programmieren“ nicht herum denke ich.

    Ich habe mich bisher auf kleine GUIs beschränkt, die einen User Input verarbeiten, deshalb habe ich mich mit dem Thema „Oberfläche friert ein“ noch nicht beschäftigt.

    Es gab mal für PowerShell die beiden WPF basierten Ansätze PowerBoots und Microsoft PowerShell Power Pack (WPK) diese hatten die Möglichkeit die GUI als Job zu starten.
    Die Entwickler von WPK und PowerBoots haben sich zusammengetan und haben ein neues PowerShell WPF Produkt entwickelt das nennt sich PowerShell ShowUI:
    http://showui.codeplex.com/
    http://huddledmasses.org/showui-tutorial-walkthrough/
    http://show-ui.com/?Walkthru=Getting%20started%20with%20ShowUI

    Für Show UI und WPF gibt es auch einen Online Designer:
    http://www.poshboard.com/Designer/Default.html

    PowerShell startet normalerweise im Multithread Apartment Modus (MTA), WPF braucht aber den Single Thread Apartment (STA)  Modus deshalb wird hier schon etwas schwierig.
    (Einige Windows Forms laufen mit dem STA auch besser)

    Aber nochmal zu 2.)
    Um einen neuen Thread vom Prozess abzuspalten war schon unter Visual Basic 6 der Timer sehr beliebt:
    http://www.reddit.com/r/PowerShell/comments/s74rf/avoiding_gui_lockup_when_running_a_command_eg_a/

    Anstatt des Background Workers empfiehlt der MVP Keith Hill Register-ObjectEvent  zu nutzen:
    http://stackoverflow.com/questions/3969793/powershell-backgroundworker


    Please click “Mark as Answer” if my post answers your question and click Vote as Help if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als Hilfreich und Beiträge die deine Frage ganz oder teilweise beantwortet haben als Antwort.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '


    Montag, 2. Juli 2012 09:05
  • Stimmt. Wer lesen kann ist klar im Vorteil. :-) Hatte in deinem Link wohl nicht konzentriert zu Ende gelesen. Hatte beim drüberschauen zuerst gedacht, dass dieses get-WmiObject dieses DoEvents auslöst. War ich wohl etwas verwirrt...

    Werde hier in der Umsetzung mal mit deinen Angegebenen Hinweisen etwas rumspielen und versuchen ein Gefühl dafür zu bekommen, was für meinen Fall wirklich am passensten ist. Sieht nach einem gepflegten Abend am Computer aus. Werde mein Ergebnis hier natürlich posten...

    Danke

    Montag, 2. Juli 2012 09:18
  • DoEvents ist mit Vorsicht zu benutzen, da es unerwartete Nebenwirkungen haben kann.
    Siehe  hier: Is do Events evil?

    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".

    Dienstag, 3. Juli 2012 13:47
    Moderator