none
Funktionen / GUIs nicht richtig eingebunden? RRS feed

  • Frage

  • Hallo!

    Ich habe vor kurzer Zeit mein erstes "größeres" Skript fertig geschrieben und komme nun beim Troubleshooting nicht weiter. Das Skript an sich ist funktionsfähig, allerdings nur in der ISE. Grob gesagt werden in dem Skript zwei Dateien verglichen und zu einer dritten zusammengefasst. Das alles soll der User per Klick auswählen - weswegen die Benutzereingabe der Speicherorte der Dateien etwa durch Dialog-Boxen und Speichern-Unter-Fenster geregelt ist. Beim Starten des Skripts erscheint auch ein "Hauptfenster", dass durch den Vorgang leitet.

    Mir ist bewusst, dass sich PowerShell nicht wirklich für GUI-Programmierung anbietet, aber dennoch funktioniert mein Skript und mehr soll daraus nicht werden. Das Problem liegt jedenfalls nicht in der Syntax, sondern irgendwo anders. Das weiß ich, weil das Skript in der ISE einwandfrei funktioniert, in der normalen Shell (also Rechtsklick auf das Skript im Verzeichnis--> mit PS ausführen) aber nicht.

    Ich dachte zunächst an ExecutionPolicy und habe den Wert in der Registry testweise auf unrestricted gesetzt. Jetzt lässt sich das Skript auch mit der normalen Shell öffnen, allerdings geschieht alles in der Konsole, obwohl ich möchte, dass GUIs erscheinen. Information: Da ich alle Benutzereingaben im Skript auf GUI-Ebene geschehen lasse, habe ich am Anfang des Skriptes vier Funktionen erstellt, die jeweils z.B. die oben genannten Windows-Boxen aufrufen o.ä. Ich habe den Code mal separat in einem Skript gespeichert und ausgeführt - und siehe da, gleiches Problem. Es handelt sich also um

    die Funktionsdeklaration

    Function global:Select-FileDialog
    {
    	param([string]$Title)
    	[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
    	$objForm = New-Object System.Windows.Forms.OpenFileDialog
    	$objForm.InitialDirectory = "C:\"
    	$objForm.Filter = "DAT-Dateien (*.dat)|*.dat"
    	$objForm.Title = $Title
    	$objForm.ShowDialog()
    }

    und den

    Auruf der Funktion

    $path_dat1 = Select-FileDialog -Title "Auswahl der alten DAT-Datei"       

    Ich habe beide Codes als eigenes Skript gespeichert. Führe ich die Funktionsdefinition aus, geht die Shell kurz auf und wieder zu. Führe ich danach den Aufruf der Funktion aus, geht die Shell ebenfalls auf und wieder zu - allerdings mit roter Fehlermeldung. Lasse ich mir von -noexit helfen, sagt mir PS "Select-FileDialog" wurde nicht als cmdlet(, etc.) erkannt. Zur Erinnerung: In meinem eigentlich Skript stehen vier dieser Funktionen am Anfang, und die Aufrufe zu verschiedensten Zeiten im Skript laufen problemlos ab - aber alles eben nur in der ISE.

    Ich möchte mein Skript gern einfach ausführbar machen. Was kann/hat die ISE, was die normale Standardshell nicht kann bzw. hat? Weder Zertifikate, noch das Ändern der ExecutionPolicy hat etwas gebracht. Natürlich führe ich die Skript als Administrator aus und das Ausführen von Skripts ist von unseren GPOs nicht geblockt.

    Vielen Dank für jegliche Ideen.

    So far,

    Scriptex


    • Bearbeitet Scriptex Donnerstag, 3. Mai 2012 09:01
    Donnerstag, 3. Mai 2012 09:01

Antworten

  • Nimm das, füge es in der PowerShell ISE ein, lass es laufen und achte beim drücken der Buttons auf die ausgabe in der ISE!
    Schau dir dazu unbedingt mein YouTube Video an! Das handelt nämlich genau von PowerShell und Windows Forms !
    http://youtu.be/y76LO5VIN24

    #Generated Form Function
    function GenerateForm {
    ########################################################################
    # Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.10.0
    ########################################################################
    
    #region Import the Assemblies
    [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
    [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
    #endregion
    
    #region Generated Form Objects
    $Abfrage = New-Object System.Windows.Forms.Form
    $BtnSaveFile = New-Object System.Windows.Forms.Button
    $label1 = New-Object System.Windows.Forms.Label
    $BtnRun = New-Object System.Windows.Forms.Button
    $BtnCancel = New-Object System.Windows.Forms.Button
    $BtnOpenFile2 = New-Object System.Windows.Forms.Button
    $BtnOpenFile1 = New-Object System.Windows.Forms.Button
    $saveFileDialog1 = New-Object System.Windows.Forms.SaveFileDialog
    $openFileDialog1 = New-Object System.Windows.Forms.OpenFileDialog
    $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
    #endregion Generated Form Objects
    
    #----------------------------------------------
    #Generated Event Script Blocks
    #----------------------------------------------
    #Provide Custom Code for events specified in PrimalForms.
    $handler_BtnOpenFile2_Click= 
    {
    #TODO: Place custom script here
    	$openFileDialog1.InitialDirectory = "C:\"
    	$openFileDialog1.Filter = "DAT-Dateien (*.dat)|*.dat"
    	$OpenFile = $openFileDialog1.ShowDialog()
    	Write-Host $OpenFile
    }
    
    $handler_BtnRun_Click= 
    {
    #TODO: Place custom script here
    	Write-Host "RUN wurde gedrückt! Hier soll ich was tun!"
    }
    
    $handler_BtnOpenFile1_Click= 
    {
    #TODO: Place custom script here
    	$openFileDialog1.InitialDirectory = "C:\"
    	$openFileDialog1.Filter = "DAT-Dateien (*.dat)|*.dat"
    	$OpenFile = $openFileDialog1.ShowDialog()
    	Write-Host $OpenFile
    }
    
    $handler_BtnSaveFile_Click= 
    {
    #TODO: Place custom script here
    	$SafeFile= $saveFileDialog1.ShowDialog()
    	Write-Host $SafeFile
    }
    
    $handler_BtnCancel_Click= 
    {
    #TODO: Place custom script here
    	Write-Host "Cancel wurde gedrückt! Und Tschüss!"
    	$Abfrage.close()
    }
    
    $OnLoadForm_StateCorrection=
    {#Correct the initial state of the form to prevent the .Net maximized form issue
    	$Abfrage.WindowState = $InitialFormWindowState
    }
    
    #----------------------------------------------
    #region Generated Form Code
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 167
    $System_Drawing_Size.Width = 379
    $Abfrage.ClientSize = $System_Drawing_Size
    $Abfrage.DataBindings.DefaultDataSourceUpdateMode = 0
    $Abfrage.Name = "Abfrage"
    $Abfrage.Text = "Datei auswählen!"
    
    
    $BtnSaveFile.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 248
    $System_Drawing_Point.Y = 64
    $BtnSaveFile.Location = $System_Drawing_Point
    $BtnSaveFile.Name = "BtnSaveFile"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 32
    $System_Drawing_Size.Width = 105
    $BtnSaveFile.Size = $System_Drawing_Size
    $BtnSaveFile.TabIndex = 5
    $BtnSaveFile.Text = "SaveFile"
    $BtnSaveFile.UseVisualStyleBackColor = $True
    $BtnSaveFile.add_Click($handler_BtnSaveFile_Click)
    
    $Abfrage.Controls.Add($BtnSaveFile)
    
    $label1.DataBindings.DefaultDataSourceUpdateMode = 0
    $label1.Dock = 1
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 0
    $System_Drawing_Point.Y = 0
    $label1.Location = $System_Drawing_Point
    $label1.Name = "label1"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 60
    $System_Drawing_Size.Width = 379
    $label1.Size = $System_Drawing_Size
    $label1.TabIndex = 4
    $label1.Text = "Bitte zwei Dateien auswählen und den Speicherort der Ergebnisdatei angeben."
    
    $Abfrage.Controls.Add($label1)
    
    
    $BtnRun.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 213
    $System_Drawing_Point.Y = 119
    $BtnRun.Location = $System_Drawing_Point
    $BtnRun.Name = "BtnRun"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 36
    $System_Drawing_Size.Width = 83
    $BtnRun.Size = $System_Drawing_Size
    $BtnRun.TabIndex = 3
    $BtnRun.Text = "Run"
    $BtnRun.UseVisualStyleBackColor = $True
    $BtnRun.add_Click($handler_BtnRun_Click)
    
    $Abfrage.Controls.Add($BtnRun)
    
    
    $BtnCancel.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 121
    $System_Drawing_Point.Y = 119
    $BtnCancel.Location = $System_Drawing_Point
    $BtnCancel.Name = "BtnCancel"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 36
    $System_Drawing_Size.Width = 86
    $BtnCancel.Size = $System_Drawing_Size
    $BtnCancel.TabIndex = 2
    $BtnCancel.Text = "Cancel"
    $BtnCancel.UseVisualStyleBackColor = $True
    $BtnCancel.add_Click($handler_BtnCancel_Click)
    
    $Abfrage.Controls.Add($BtnCancel)
    
    
    $BtnOpenFile2.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 128
    $System_Drawing_Point.Y = 62
    $BtnOpenFile2.Location = $System_Drawing_Point
    $BtnOpenFile2.Name = "BtnOpenFile2"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 34
    $System_Drawing_Size.Width = 114
    $BtnOpenFile2.Size = $System_Drawing_Size
    $BtnOpenFile2.TabIndex = 1
    $BtnOpenFile2.Text = "OpenFile2"
    $BtnOpenFile2.UseVisualStyleBackColor = $True
    $BtnOpenFile2.add_Click($handler_BtnOpenFile2_Click)
    
    $Abfrage.Controls.Add($BtnOpenFile2)
    
    
    $BtnOpenFile1.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 14
    $System_Drawing_Point.Y = 62
    $BtnOpenFile1.Location = $System_Drawing_Point
    $BtnOpenFile1.Name = "BtnOpenFile1"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 34
    $System_Drawing_Size.Width = 108
    $BtnOpenFile1.Size = $System_Drawing_Size
    $BtnOpenFile1.TabIndex = 0
    $BtnOpenFile1.Text = "OpenFile1"
    $BtnOpenFile1.UseVisualStyleBackColor = $True
    $BtnOpenFile1.add_Click($handler_BtnOpenFile1_Click)
    
    $Abfrage.Controls.Add($BtnOpenFile1)
    
    $saveFileDialog1.CreatePrompt = $True
    $saveFileDialog1.ShowHelp = $True
    
    $openFileDialog1.ShowHelp = $True
    
    #endregion Generated Form Code
    
    #Save the initial state of the form
    $InitialFormWindowState = $Abfrage.WindowState
    #Init the OnLoad event to correct the initial state of the form
    $Abfrage.add_Load($OnLoadForm_StateCorrection)
    #Show the Form
    $Abfrage.ShowDialog()| Out-Null
    
    } #End Function
    
    #Call the Function
    GenerateForm


    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' '



    • Als Antwort markiert Scriptex Freitag, 4. Mai 2012 11:37
    • Bearbeitet Peter Kriegel Freitag, 4. Mai 2012 14:00
    Freitag, 4. Mai 2012 11:28

Alle Antworten

  • Sieh mal hier : http://social.technet.microsoft.com/Forums/de-DE/powershell_de/thread/515becb7-0bac-4a89-9b53-dbd36ff04ae3

    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' '

    Donnerstag, 3. Mai 2012 09:33
  • >Mir ist bewusst, dass sich PowerShell nicht wirklich für GUI-Programmierung anbietet

    Wer behauptet denn sowas?

    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".

    Donnerstag, 3. Mai 2012 09:53
    Moderator
  • @Peter:

    Vielen Dank für die Mühe. Ich habe in dem Befehl

    PowerShell.exe -STA -File <Pfad\Skriptname.ps1>

    meinen Pfad eingesetzt. Da das Skript aber unter eigene Dateien liegt und die Pfadeingabe mit Anführungszeichen nicht funktionierte, habe ich das Skript auf den Desktop kopiert und den dortigen Pfad genutzt. Leider erscheint wieder alles nur im Konsolenfenster, keine GUI geht auf.

    Die Links habe ich mir auch angeschaut. Ein paar Fragen zu deinem Post:

    Kann ich die If-Abfrage so vor mein Test-Skript stellen oder muss ich dort

    $MyInvocation.MyCommand.Definition

    durch den Pfad zu meinem Skript ersetzen? Das habe ich leider noch nie so gesehen.

    Du hast den Code des Threaderstellers so modifiziert, dass hinter If und Else in der gleichen Zeile die geschweifte Klammer erscheint. Habe ich etwas übersehen oder ist dies die einzige Veränderung in der Syntax, die das Skript zum laufen in STA nötig hat?

    Danke schon einmal.

    @Denniver

    Mir erscheint es ab und an etwas umständlich, etwas grafisch/benutzerfreundlich auszugeben. Ich persönlich brauche keine GUIs zum glücklich sein, da komme ich besser mit schlichten Ein- und Ausgaben ohne Schnickschnack zurecht. Für jemand anderen schreibe ich jedoch gern mit GUIs. Da stolpere ich über Funktionen, COM-Objekte, .NET, das richtige Einbinden, Modul-Import... und bekomme teilweise den Eindruck, die Shell muss sich erst alles von hier und dort "zusammensuchen", um damit arbeiten zu können. Ich habe außerdem PowerShell als Werkzeug "unter" dem OS kennengelernt, also fernab der GUIs. Das spielt da sicherlich auch mit rein. ;-) Dass es mit etwas Übung trotzdem funktioniert, spricht aber noch mehr für PowerShell. Zudem kann ich nur den Vergleich zu ein paar wenigen  C++-Kenntnissen ziehen, wo mir der Umgang mit spezieller Benutzerein-/Ausgabe doch etwas leichter fiel. Da ist also das Ende der Fahnenstange bei mir noch lange nicht in Sicht.

    So far,

    Scriptex

    Donnerstag, 3. Mai 2012 10:18
  • Ich denke sogar das die PowerShell genauso eine Karriere machen wird/soll wie z.B. Phyton unter Linux.
    Dort sind sehr viele standard GUI Programme, in einer Scriptsprache geschrieben.
    PowerShell ist .NET und .NET ist auch für die GUI gut geignet.
    Das Problem mit dem TreadAppartment ist da nicht so schlimm wenn man es kennt.

    Es fehlt bisher nur an GUI designern (kostenlos wenns geht).
    Die Firma Sapien hat da was im Programm!

    Du findest in Denniver seinem Blog eine gute Anleitung (englisch) und ich habe darüber ein Youtube Video gemacht (deutsch) (siehe meinem Blog)


    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' '

    Donnerstag, 3. Mai 2012 10:21
  • Ah! Wart mal ....
    OpenfileDialog hat einen bekannten Bug!
    Füge mal in deinem code folgende Zeile ein:

    $objForm.ShowHelp = $true

    Function global:Select-FileDialog
    {
    	param([string]$Title)
    	[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
    	$objForm = New-Object System.Windows.Forms.OpenFileDialog
        $objForm.ShowHelp = $true
    	$objForm.InitialDirectory = "C:\"
    	$objForm.Filter = "DAT-Dateien (*.dat)|*.dat"
    	$objForm.Title = $Title
    	$objForm.ShowDialog()
    }

    Dies sollte auch ohne Single ThreadAppartment laufen (STA)


    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' '



    Donnerstag, 3. Mai 2012 10:30
  • Danke für den Hinweis.

    Leider funktioniert es immer noch nicht. Ich tippe auf einen Fehler bei der Einbindung. Ich habe jetzt:

    • beide Skripts (Definition und Aufruf) nacheinander mithilfe von -STA gestartet. Ergebnis: GUI erscheint nicht, alles erscheint im Konsolenfenster
    • den genannten Bug gefixt und den vorigen Schritt nochmal ausgeführt. Ergebnis: Mein cmdlet wird auf einmal nicht mehr erkannt.
    • beide Möglichkeiten in der ISE ausgeführt. Ergebnis: Es läuft nur alles korrekt, wenn ich die Zeile nicht hinzufüge.

    Wie kann das sein? Ich weise die Konsole doch schon an, in STA zu starten. Warum ist dann keine GUI möglich?

    Edit: Tritt der Bug auch bei SaveFile-Dialog auf?



    • Bearbeitet Scriptex Donnerstag, 3. Mai 2012 10:45
    Donnerstag, 3. Mai 2012 10:42
  • Nicht, dass es falsch verstanden wird:

    Dein Code funktioniert sehr wohl in beiden Umgebungen. Das tat meiner ebenfalls. Das Problem tritt dann erst auf, wenn ich das cmdlet benenne und abrufe. Und da werde ich nicht schlau draus... Wenn die Funktion global gilt, Powershell mit STA startet und der Bug auch gefixt ist, (...etc) funktioniert es immer noch nicht.

    Da gehen einem ja langsam die Lösungen aus...

    So far,

    Scriptex

    Donnerstag, 3. Mai 2012 11:08
  • Ja! SavefileDialog hat diesen Bug auch!

    Ich habe den Code den ich die geposted habe, getestet!
    Windows 7 PowerShell 2.0. Copy + Paste die Funktion in die Konsole, 2mal Enter und Funktion aufrufen ! geht!

    Geht das Fenster hinter dem Konsolen fenster auf ?


    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' '

    Donnerstag, 3. Mai 2012 11:24
  • Also jetzt bin ich vollkommen baff, Peter.

    Wenn ich den Code händisch per Copy&Paste in die Konsole einfüge und dann enter drücke, passiert erstmal nichts. Drücke ich dann wieder enter - wie du geschrieben hast - kann ich wieder etwas eingeben. Gebe ich also den Aufruf ein, erscheint die GUI, vor der Konsole.

    Jetzt gehen also zwei von drei Möglichkeiten (Skript in der ISE ausführen, Funktion händisch einbinden). Doch - wie sollte es anders sein - bräuchte ich ja die dritte; also das Ausführen von einem Skript mit demselben Inhalt. Kopiere ich also wieder deinen Code, füge ihn in ein Testskript ein und in ein anderes den Aufruf, führe beide nacheinander aus - geht es nicht.

    So far,

    Scriptex


    EDIT: Das Testskript funktioniert, wenn ich Funktion und Aufruf in ein Skript setze. Logisch, dass es nicht funktioniert, wenn ich zwei daraus mache: Dann ist ja in dem Skript, wo die Funktion aufgerufen wird, sie gar nicht implementiert. Ich schaue mir jetzt nochmal deinen Code an (vielleicht lag es ja wirklich am Bug), was da der Unterschied zu meinem ist, und berichtige das im Hauptskript. Melde mich dann.
    • Bearbeitet Scriptex Donnerstag, 3. Mai 2012 11:45
    Donnerstag, 3. Mai 2012 11:45
  • Also, vorab schonmal recht herzlich Dank, das Problem mit den OpenFile- und SaveFile-DialogBoxen ist wohl gelöst. Das Hauptskript läuft in der ISE auch ohne die Bugfixes glatt, schreibe ich aber wie oben gesagt nur die Definition und den Aufruf in ein Skript, funktioniert es nur mit dem Bugfix. Vielen Dank dafür.

    Mein Hauptskript läuft allerdings immer noch in der Konsole, wenn ich es starte. Das liegt (denke ich) an der Haupt-GUI, die dauerhaft auf dem Bildschirm erscheint. Den Code habe ich nur leicht verändert, ursprünglich habe ich ihn aus dem Netz. Wenn es dort kein Problem gäbe, würde ja beim normalen Ausführen eine GUI erscheinen - das ist ja zu 100% möglich, wie Select-FileDialog bewiesen hat. Ergo muss was bei der GUI in Zusammenhang mit der Konsole nicht stimmen.

    Function global:Select-File { Param([String[]]$choiceList,[int]$default=0) $choicedesc = New-Object System.Collections.ObjectModel.Collection[System.Management.Automation.Host.ChoiceDescription] $choiceList | foreach { $choicedesc.Add((New-Object "System.Management.Automation.Host.ChoiceDescription" -ArgumentList $_))} $Caption="#### Test-Programm ####" $Message="INSERT RANDOM TEXT" $Host.ui.PromptForChoice($caption, $message, $choicedesc, $default) } Select-File -choice "1","2","3","Run","Cancel"

    Der Code wirkt auf mich etwas wüst und unübersichtlich, zumal mir da nicht jedes Wort etwas sagt. Ich kann mir ihn jedoch grob erklären und außerdem tut er das, was ich sehen wollte - in der ISE. Wenn ich ihn wie gesagt in der Konsole ausführe, erscheint der Text und alles weitere in der Konsole. Es darf gern getestet werden.

    Im Hauptskript verarbeitet dann ein Switch-cmdlet den Klick des Users und leitet die Eingabe durch verschiedene If-Abfragen durch das Skript.

    Scriptex

    Donnerstag, 3. Mai 2012 12:06
  • Ja! Ich hatte mich zuerst auf die üblichen Verdächtigen gestürzt und überlesen das du ein Skript von einem anderen Skript startest.

    Das scheint also ein Scope (Gültigkeitsbereich) Problem zu sein.

    Wenn du ein Skript von eine anderen aus starten möchtest, dann solltest du bei dem Aufruf des Skriptes Dot-Sourcing benutzen.

    Siehe:  < Get-Help about_Scripts  > dort SKRIPTBEREICH UND DOT-QUELLENTNAHME (fürchterliche deutsch Übersetzung für Dot-Sourcing)

    >>>>    Jedes Skript wird in einem eigenen Bereich ausgeführt. Die
        Funktionen, Variablen, Aliase und Laufwerke, die im Skript
        erstellt werden, sind nur im Skriptbereich vorhanden.  <<<<

    Damit die Funktionen und anderes im selben Scope (Gültigkeitsbereich) befinden, nutzt man Dot-Sourcing beim Aufruf.
    Geben Sie für das Dot-Sourcing eines Skripts einen Punkt (.) und ein Leerzeichen vor dem Skriptpfad ein.

        Beispiel:

            . C:\scripts\UtilityFunctions.ps1

        -oder-

            . .\UtilityFunctions.ps1


    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' '



    Donnerstag, 3. Mai 2012 12:24
  • Dem Dot-Sourcing bin ich auch recht früh beim Schreiben des Skriptes über den Weg gelaufen; anfangs, weil ich ja drei verschiedene Funktionen benutze und die natürlich einbinden muss. Allerdings wollte ich dann auch ganz schnell wieder weg vom Dot-Sourcing - da ich nicht dem interessierten Kollegen/User dann zwei,drei, vier Skripts schicken möchte, sondern eines - das er ausführt und durch das er sich durchklickt.

    Daher ist mir eben beim Ausprobieren mit OpenFileDialog aufgefallen, dass diese Funktion im Skript erst nach einer anderen kommt - der Haupt-GUI. Wenn ich das Skript ausführe, ist immer diese GUI präsent (der in meinem vorigen Post angehängte Code "Select-File") und führt mich dann zu OpenFileDialog und SaveFileDialog, wenn ich auf die entsprechenden Buttons klicke.

    Da aber diese "Select-File"-GUI nur in der ISE aufgeht, und nicht in der Konsole, kann ich beim normalen Ausführen des Skriptes nichts anklicken. Die GUI erscheint nicht. Folglich muss dort irgendwas im Zusammenhang mit dem Aufruf in der Konsole nicht zusammenpassen. Das ist das einzig übrig gebliebene Problem - erscheint meine GUI nicht, habe ich auch keine fünf Auswahl-Buttons, und kann auch keine Eingabe machen. Warum erscheint also die GUI in der ISE und nicht in der Konsole, wenn ich andere GUIs doch über die Konsole aufrufen kann. Das ist meine Frage.

    Trotzdem vielen Dank für deine Mühen bis hierhin! Ich melde mich ab morgen, früher Mittag, wieder.

    So far,

    Scriptex




    • Bearbeitet Scriptex Donnerstag, 3. Mai 2012 12:47
    Donnerstag, 3. Mai 2012 12:45
  • Tja da binn ich auch langsam überfragt...
    Was noch helfen könnte wenn ich/wir dein ganzes Skript hätte/n.

    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' '

    Freitag, 4. Mai 2012 07:43
  • Ich will zuerst mal aufdröseln, woran es noch hakt.

     

    Oben die Posts haben sich alle mit zwei Funktionen beschäftigt, die mein Skript enthält, und von denen ich dachte, sie wären der Grund für mein Problem.

    Doch beim Hinzufügen der Bugfixes ist mir aufgefallen, dass vor dem Aufruf der beiden eine andere ganz am Anfang steht. Und mit dieser stimmt irgendetwas nicht. Ich will mein Skript eigentlich nur ungern posten, da es sehr lang ist und der Teil, der das Problem verursacht, auch in einem separaten Skript abgespeichert denselben "Fehler" verursacht. So hängt nicht der ganze Rest mit hinten dran, der sowieso nur dann ausgeführt werden würde, wenn der fehlerhafte Teil korrekt liefe.

     

    Zum Ablauf/Aufbau: Das Skript wird gestartet, die drei Funktionen werden definiert, und die GUI erscheint. Sie hat fünf Buttons - einer zum Vergleichen, zwei zum Auswählen der beiden Dateien, einen zum Auswählen des Speicherortes und einen zum Abbrechen - und erscheint solange, bis der User auf den "Vergleichen/Run"-Button oder den Cancel-Button drückt. Ersterer hat nur dann die gewünschte Wirkung, wenn die Dateien und der Speicherort ausgewählt ist, ansonsten gibt es eine Fehlermeldung.

    Selbst so tief brauch man imo aber gar nicht gehen, denn der Text und die Auswahlmöglichkeiten werden angezeigt. Unterschied (und damit das Problem): Beim Ausführen in der ISE erscheint die GUI, in der Konsole (reguläres Ausführen) erscheint der gesamte Inhalt in der Konsole - auch nett mit Auswahlmöglichkeiten gemacht - aber ich kann nichts anklicken oder eingeben.

     

    Daher tippe ich auf einen Fehler, der das Aufrufen dieser GUI in der Konsole nicht zulässt - eine Einstellung,  ein fehlender Parameter, eine fehlende Zeile in der Funktion - was auch immer. OpenFile und SaveFile kommen also viel viel später ins Spiel.

    Funktioniert diese Haupt-GUI, funktioniert auch der Rest, da ich als User dann alles bedienen kann.

    Code:

    Function global:Select-File
        {
        Param([String[]]$choiceList,[int]$default=0)
        $choicedesc = New-Object System.Collections.ObjectModel.Collection[System.Management.Automation.Host.ChoiceDescription]
        $choiceList | foreach  { $choicedesc.Add((New-Object "System.Management.Automation.Host.ChoiceDescription" -ArgumentList $_))}
        $Caption="#### Vergleichs-Programm ####"
        $Message="
        Bitte zwei Dateien auswählen und den Speicherort der Ergebnisdatei angeben."
        $Host.ui.PromptForChoice($caption, $message, $choicedesc, $default)
        }
    Select-File -choice "OpenFileDialog","OpenFileDialog","SaveFileDialog","Run","Cancel"

    Ich habe versucht, die Formulierungen ein bisschen verständnisvoller zu wählen.

    So far,

    Scriptex



    • Bearbeitet Scriptex Freitag, 4. Mai 2012 08:59
    Freitag, 4. Mai 2012 08:57
  • Nun ist, glaube ich, alles klar !

    Du benutzt hier in dieser Funktion keine Windows.Forms sondern den PowerShell Host als ausgabe!

    System.Management.Automation.Host.ChoiceDescription

    Der PowerShell Host ist das Programm das das die Grafische Benutzeroberfläche bereitstellt und die Benutzer eingaben annimmt. Die PowerShell Engine verarbeitet dann die Befehle die vom Host kommen und gibt die Ergebnisse an den Host zum Anzeigen zurück!

    Deshalb sind die Ergebnisse in jedem Host (ISE/Konsole) anders!
    Da das Konsolenfenster eben nur das Konsolenfenster als Ausgabe hat erscheint das in der Konsole und nicht wie bei dem ISE Host in einem eigenen Fenster. Die PowerShell  ISE macht das von sich aus genauso wie bei z.B. Write-Progress !

    Dein so genanntes Startfenster ist also gar kein Startfenster sondern ein Befehl der von den verschiedenen Hosts verschieden dargestellt wird.

    Gib mir mal ein bisschen Zeit ich bastle da mal was…

    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' '


    Freitag, 4. Mai 2012 10:50
  • Nimm das, füge es in der PowerShell ISE ein, lass es laufen und achte beim drücken der Buttons auf die ausgabe in der ISE!
    Schau dir dazu unbedingt mein YouTube Video an! Das handelt nämlich genau von PowerShell und Windows Forms !
    http://youtu.be/y76LO5VIN24

    #Generated Form Function
    function GenerateForm {
    ########################################################################
    # Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.10.0
    ########################################################################
    
    #region Import the Assemblies
    [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
    [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
    #endregion
    
    #region Generated Form Objects
    $Abfrage = New-Object System.Windows.Forms.Form
    $BtnSaveFile = New-Object System.Windows.Forms.Button
    $label1 = New-Object System.Windows.Forms.Label
    $BtnRun = New-Object System.Windows.Forms.Button
    $BtnCancel = New-Object System.Windows.Forms.Button
    $BtnOpenFile2 = New-Object System.Windows.Forms.Button
    $BtnOpenFile1 = New-Object System.Windows.Forms.Button
    $saveFileDialog1 = New-Object System.Windows.Forms.SaveFileDialog
    $openFileDialog1 = New-Object System.Windows.Forms.OpenFileDialog
    $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
    #endregion Generated Form Objects
    
    #----------------------------------------------
    #Generated Event Script Blocks
    #----------------------------------------------
    #Provide Custom Code for events specified in PrimalForms.
    $handler_BtnOpenFile2_Click= 
    {
    #TODO: Place custom script here
    	$openFileDialog1.InitialDirectory = "C:\"
    	$openFileDialog1.Filter = "DAT-Dateien (*.dat)|*.dat"
    	$OpenFile = $openFileDialog1.ShowDialog()
    	Write-Host $OpenFile
    }
    
    $handler_BtnRun_Click= 
    {
    #TODO: Place custom script here
    	Write-Host "RUN wurde gedrückt! Hier soll ich was tun!"
    }
    
    $handler_BtnOpenFile1_Click= 
    {
    #TODO: Place custom script here
    	$openFileDialog1.InitialDirectory = "C:\"
    	$openFileDialog1.Filter = "DAT-Dateien (*.dat)|*.dat"
    	$OpenFile = $openFileDialog1.ShowDialog()
    	Write-Host $OpenFile
    }
    
    $handler_BtnSaveFile_Click= 
    {
    #TODO: Place custom script here
    	$SafeFile= $saveFileDialog1.ShowDialog()
    	Write-Host $SafeFile
    }
    
    $handler_BtnCancel_Click= 
    {
    #TODO: Place custom script here
    	Write-Host "Cancel wurde gedrückt! Und Tschüss!"
    	$Abfrage.close()
    }
    
    $OnLoadForm_StateCorrection=
    {#Correct the initial state of the form to prevent the .Net maximized form issue
    	$Abfrage.WindowState = $InitialFormWindowState
    }
    
    #----------------------------------------------
    #region Generated Form Code
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 167
    $System_Drawing_Size.Width = 379
    $Abfrage.ClientSize = $System_Drawing_Size
    $Abfrage.DataBindings.DefaultDataSourceUpdateMode = 0
    $Abfrage.Name = "Abfrage"
    $Abfrage.Text = "Datei auswählen!"
    
    
    $BtnSaveFile.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 248
    $System_Drawing_Point.Y = 64
    $BtnSaveFile.Location = $System_Drawing_Point
    $BtnSaveFile.Name = "BtnSaveFile"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 32
    $System_Drawing_Size.Width = 105
    $BtnSaveFile.Size = $System_Drawing_Size
    $BtnSaveFile.TabIndex = 5
    $BtnSaveFile.Text = "SaveFile"
    $BtnSaveFile.UseVisualStyleBackColor = $True
    $BtnSaveFile.add_Click($handler_BtnSaveFile_Click)
    
    $Abfrage.Controls.Add($BtnSaveFile)
    
    $label1.DataBindings.DefaultDataSourceUpdateMode = 0
    $label1.Dock = 1
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 0
    $System_Drawing_Point.Y = 0
    $label1.Location = $System_Drawing_Point
    $label1.Name = "label1"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 60
    $System_Drawing_Size.Width = 379
    $label1.Size = $System_Drawing_Size
    $label1.TabIndex = 4
    $label1.Text = "Bitte zwei Dateien auswählen und den Speicherort der Ergebnisdatei angeben."
    
    $Abfrage.Controls.Add($label1)
    
    
    $BtnRun.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 213
    $System_Drawing_Point.Y = 119
    $BtnRun.Location = $System_Drawing_Point
    $BtnRun.Name = "BtnRun"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 36
    $System_Drawing_Size.Width = 83
    $BtnRun.Size = $System_Drawing_Size
    $BtnRun.TabIndex = 3
    $BtnRun.Text = "Run"
    $BtnRun.UseVisualStyleBackColor = $True
    $BtnRun.add_Click($handler_BtnRun_Click)
    
    $Abfrage.Controls.Add($BtnRun)
    
    
    $BtnCancel.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 121
    $System_Drawing_Point.Y = 119
    $BtnCancel.Location = $System_Drawing_Point
    $BtnCancel.Name = "BtnCancel"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 36
    $System_Drawing_Size.Width = 86
    $BtnCancel.Size = $System_Drawing_Size
    $BtnCancel.TabIndex = 2
    $BtnCancel.Text = "Cancel"
    $BtnCancel.UseVisualStyleBackColor = $True
    $BtnCancel.add_Click($handler_BtnCancel_Click)
    
    $Abfrage.Controls.Add($BtnCancel)
    
    
    $BtnOpenFile2.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 128
    $System_Drawing_Point.Y = 62
    $BtnOpenFile2.Location = $System_Drawing_Point
    $BtnOpenFile2.Name = "BtnOpenFile2"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 34
    $System_Drawing_Size.Width = 114
    $BtnOpenFile2.Size = $System_Drawing_Size
    $BtnOpenFile2.TabIndex = 1
    $BtnOpenFile2.Text = "OpenFile2"
    $BtnOpenFile2.UseVisualStyleBackColor = $True
    $BtnOpenFile2.add_Click($handler_BtnOpenFile2_Click)
    
    $Abfrage.Controls.Add($BtnOpenFile2)
    
    
    $BtnOpenFile1.DataBindings.DefaultDataSourceUpdateMode = 0
    
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 14
    $System_Drawing_Point.Y = 62
    $BtnOpenFile1.Location = $System_Drawing_Point
    $BtnOpenFile1.Name = "BtnOpenFile1"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 34
    $System_Drawing_Size.Width = 108
    $BtnOpenFile1.Size = $System_Drawing_Size
    $BtnOpenFile1.TabIndex = 0
    $BtnOpenFile1.Text = "OpenFile1"
    $BtnOpenFile1.UseVisualStyleBackColor = $True
    $BtnOpenFile1.add_Click($handler_BtnOpenFile1_Click)
    
    $Abfrage.Controls.Add($BtnOpenFile1)
    
    $saveFileDialog1.CreatePrompt = $True
    $saveFileDialog1.ShowHelp = $True
    
    $openFileDialog1.ShowHelp = $True
    
    #endregion Generated Form Code
    
    #Save the initial state of the form
    $InitialFormWindowState = $Abfrage.WindowState
    #Init the OnLoad event to correct the initial state of the form
    $Abfrage.add_Load($OnLoadForm_StateCorrection)
    #Show the Form
    $Abfrage.ShowDialog()| Out-Null
    
    } #End Function
    
    #Call the Function
    GenerateForm


    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' '



    • Als Antwort markiert Scriptex Freitag, 4. Mai 2012 11:37
    • Bearbeitet Peter Kriegel Freitag, 4. Mai 2012 14:00
    Freitag, 4. Mai 2012 11:28
  • Vielen Dank!

    So ein Zeilenungetüm habe ich auch irgendwo zwischen gespeichert als "Eingabebox Eigenbau" - man baut sich da ja wirklich alles selbst. Scheinbar geht es nicht kürzer. Schade! Es funktioniert auch aus der Konsole heraus, Schönheitsfrage wäre vielleicht, ob man es so einrichten kann, dass die Konsole hitner dem Fenster nur kurz erscheint/schnell verschwindet/nicht erscheint. Ich werde mich damit mal am Wochenende beschäftigen.

    Ansonsten sehr vielen Dank!

    Scriptex


    • Bearbeitet Scriptex Freitag, 4. Mai 2012 11:35
    Freitag, 4. Mai 2012 11:35
  • >> man baut sich da ja wirklich alles selbst
    Schau mein Video an! Da gibt es Tools dafür!
    Oder glaubst du ich kann so schnell Tippen?

    Das Tool heisst: Sapien Primal Forms ;-)) (Es gibt leider zu zeit kein anderes für Windows Forms)

    >> Schönheitsfrage wäre vielleicht, ob man es so einrichten kann, dass die Konsole hitner dem Fenster nur kurz erscheint/schnell verschwindet/nicht erscheint.

    Das geht über umwege.
    Erstelle dir eine Batch oder eine Verknüpfung (.lnk) die mit PowerShell.exe dein Script startet.

    Siehe: http://technet.microsoft.com/de-de/library/dd315276.aspx

    -WindowStyle
    Legt den Fensterstil auf "Normal", "Minimized", "Maximized" oder "Hidden" fest.


    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' '



    Freitag, 4. Mai 2012 11:44