mayho33
Goto Top

Powershell Parametersets und Auswahlmöglichkeiten

Hallo @ All!

Wieder mal eine kleine Frage zu Powershell bzgl. Parameter, ParameterSets und/oder(vielleicht??) dynamische Parameter.


Ich definiere einige Parameter in einem cmdlet. Darunter auch 2 Switches. Nun möchte ich, wenn Switch A gewählt wird, das entsprechende ParameterSet auswählen "und", dass die Parameter aus ParameterSet B garnicht mehr zur Auswahl stehen. Wie mache ich das??

Ein Bsp zur Frage:

function Test-Test {
[CmdletBinding()]
param (
[Parameter(ParameterSetName="A")][Switch] $A,
[Parameter(ParameterSetName="A")][String] $Doing1,
[Parameter(ParameterSetName="A")][String] $Doing2,
[Parameter(ParameterSetName="B")][Switch] $B,
[Parameter(ParameterSetName="B")][String] $Doing3,
[Parameter(ParameterSetName="B")][String] $Doing4,
)

...
...
...
}

Nach obigem Beispiel habe ich in der ISE folgendens Phänomen:

Alle Parameter werden angezeigt:
d9d116c0d0fca4348d6402de3e752132

nach Auswahl von Switch A fehlen aber alle anderen Parameter. Keine Auswahlmöglichkeit
8fb17ee6e1526b4b57012de02cac395b


Da stimmt doch was nicht oder? Sollten nicht wenigstens -Doing1 und -Doing2 angezeigt werden??

Danke für eure Hilfe!

mayho

Content-Key: 235854

Url: https://administrator.de/contentid/235854

Ausgedruckt am: 28.03.2024 um 17:03 Uhr

Mitglied: colinardo
colinardo 17.04.2014 aktualisiert um 15:37:04 Uhr
Goto Top
Hi mayho,

Beispiel:
function test-test {
    param(
        [Parameter(ParameterSetName="A",position=0,Mandatory=$true)][switch]$A,  
        [Parameter(ParameterSetName="B",position=0,Mandatory=$true)][switch]$B,  
        [Parameter(ParameterSetName="A")][String]$DoingA1,  
        [Parameter(ParameterSetName="A")][String]$DoingA2,  
        [Parameter(ParameterSetName="B")][String]$DoingB1,  
        [Parameter(ParameterSetName="B")][String]$DoingB2  
    )
    if ($A){
        write-host "$DoingA1,$DoingA2"  
    }
    if ($B){
        write-host "$DoingB1,$DoingB2"  
    }
}

# geht jeweils problemlos
test-test -A -DoingA1 "testa1" -DoingA2 "testa2"  
test-test -B -DoingB1 "testb1" -DoingB2 "testb2"   

# das folgende wirft einen Fehler aus, weil Parameter DoingB1 ja nur Mitglied im Parameterset B ist
test-test -A -DoingB1 "testb1"  

# das folgende gibt auch einen Fehler da ein Switch fehlt
test-test -DoingA1 "abcd"  

Siehe dazu auch

Dynamische Parameter sind auch möglich mit DynamicParam {}, siehe dazu für eine Erklärung und ein Beispiel: http://technet.microsoft.com/en-us/library/dd347600.aspx ganz unten

Grüße Uwe
Mitglied: mayho33
mayho33 17.04.2014 um 16:06:29 Uhr
Goto Top
Hallo Uwe!

Ich habe gerade meinen Beitrag aktualisiert um es besser zu veranschaulichen. Eventuell ligts auch an der ISE aber in PowerGUI habe ich das gleiche Phänomen etwas anders gelagert.

lg

Mayho
Mitglied: colinardo
colinardo 17.04.2014 aktualisiert um 16:24:46 Uhr
Goto Top
hast du es denn schon nach meinem Beispiel probiert ?? Hier geht das einwandfrei. Das bei noch keiner Angabe des ersten Parameters alle angezeigt werden ist normal, da du ja erst mal den entscheidenden Parameter eingeben musst, so dass die Shell entscheiden kann welches Set du möchtest. Das wichtige ist ja das die Funktion einen Fehler auswirft wenn sie mit der falschen Parameterkombination ausgeführt wird. Die Intellisense-Funktion der ISE hat da manchmal so Ihre Schwierigkeiten ... Mal abmelden und wieder neu anmelden...

Bei meinem Beispiel sieht es so aus:
back-to-topErst mal ohne Parameter (zeigt mir alle an, ist ja klar weil die Shell noch nicht entscheiden kann welches Set man will)

9a43dbe87d40e124cf36fe277113fdf4

back-to-topBei switch A nur die Parameter von Set A verfügbar

2b1bf0223356f9981371ffb2c59a45cd

back-to-topBei Switch B nur die Parameter von Set B verfügbar

522ea1c8faa52e17bb523a7edf308cec

Grüße Uwe
Mitglied: mayho33
mayho33 17.04.2014 um 16:24:23 Uhr
Goto Top
Hi Uwe!

habe ich soeben getestet. Der Effekt ist wie oben beschrieben. Die weiteren parameter stehen nicht mehr zur Auswahl. Sollen sie aber, denn das CmdLet verwende ich nicht alleine. Es sollen auch andere damit arbeiten.

Kann ich das irgendwie anders lösen??
Mitglied: colinardo
colinardo 17.04.2014 aktualisiert um 16:32:27 Uhr
Goto Top
Zitat von @mayho33:
habe ich soeben getestet. Der Effekt ist wie oben beschrieben. Die weiteren parameter stehen nicht mehr zur Auswahl. Sollen sie aber, denn das CmdLet verwende ich nicht alleine. Es sollen auch andere damit arbeiten.
das ist nicht normal ... hier geht das bei mir überall mit meiner Variante...
Kann ich das irgendwie anders lösen??
das muss funktionieren, irgendwo bei deiner Powershell-Version ist da ein Wurm drin. Aktualisiere dein Powershell oder das .NET-Framework. Ich arbeite hier mit PS 3.0.

mal den Rechner neu gestartet ? Die ISE kann sich derb aufhängen ... gerade die IntelliSense !
Mitglied: mayho33
mayho33 17.04.2014 um 16:33:12 Uhr
Goto Top
Hi!

Lustig! PS ist aktuell:

PS C:\WINDOWS\system32> $PSVersionTable

PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34003
BuildVersion 6.3.9600.16394
PSCompatibleVersions {1.0,2.0,3.0,4.0}
PSRemotingProtocolVersion 2.2

Was noch lustiger ist:

test-test -A Dann "2" Leerzeichen >> die zusätzlichen Parameter werden angezeigt.
Mitglied: colinardo
Lösung colinardo 17.04.2014 aktualisiert um 16:39:28 Uhr
Goto Top
test-test -A Dann "2" Leerzeichen >> die zusätzlichen Parameter werden angezeigt.
STRG+LEERTASTE hilft da auch meistens nach dem dash ...

aber das sind ja alles nur kosmetische Problemchen, und behindern nicht die Funktion, ein von dir eingebetteter Hilfetext (Synopsis) klärt die Nutzer da einfach auf.
Mitglied: mayho33
mayho33 17.04.2014 um 16:39:25 Uhr
Goto Top
Hui! Brillianter Tipp! Das ist aber ein generellen PS-Problem oder??

Somit wäre mein Problem wieder mal gelöst! Danke!!

mayho
Mitglied: colinardo
colinardo 17.04.2014 aktualisiert um 23:04:14 Uhr
Goto Top
Zitat von @mayho33:

Hui! Brillianter Tipp! Das ist aber ein generellen PS-Problem oder??
Nicht generell aber das ISE-Environment hat da oft so seine Schwierigkeiten - gerade wenn man länger damit arbeitet.
Dann kommt oft das Phänomen das die IntelliSense immer erst explizit nach STRG+Leertaste etwas anzeigt. Bei mir hilft dann immer Neustart der ISE oder kurz abmelden.

Grüße Uwe
Mitglied: mayho33
mayho33 17.04.2014 um 16:58:09 Uhr
Goto Top
Eine Frage hätte ich da aber trotzdem noch:

gebe ich Keinen der Switches an stehen alle Parameter zur Verfügung.
Wenn ich aber wollte, dass die zusätzlichen Parameter nur zur Verfügung stehen wenn ich z.B. Switch B bereits angegeben habe, wie müsste ich das dann machen?
Irgend wie die Parametersets verschachteln?? (Sorry nochmal 0 Plan)
Mitglied: colinardo
colinardo 17.04.2014, aktualisiert am 18.04.2014 um 10:48:44 Uhr
Goto Top
siehe ebenfalls meine Lösung von oben, dort habe ich die switch-Parameter als Mandatory (Pflicht) deklariert d.h. einer von beiden muss also angegeben werden, sonst wird ein Fehler getriggert.

oder du nutzt die in meinem ersten Post erwähnten dynamischen Parameter sieh Link oben (DynamicParam{}). Damit kannst du zusätzliche Parameter erst hinzufügen, wenn A oder B gewählt wurde.

back-to-topBeispiel mit dynamisch erzeugten Parametern
Hierbei werden die zu den Switch-Parametern zugehörigen Parameter erst erzeugt und somit sichtbar, wenn der entsprechende Switch verwendet wird.
function test-test {
    param(
        [parameter(ParameterSetName="A")][switch]$A,  
        [parameter(ParameterSetName="B")][switch]$B  
    )

    DynamicParam{
        
        $attrCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
        $paramDic = new-object System.Management.Automation.RuntimeDefinedParameterDictionary

        if ($A){
            # Attribute für die Parameter definieren
            $attr = new-object System.Management.Automation.ParameterAttribute
            
            # Zugehörigkeit zum ParameterSet definieren
            $attr.ParameterSetName = "A"  
            $attr.Mandatory = $false
            $attrCollection.Add($attr)

            # Parameter definieren
            $dynParam1 = new-object System.Management.Automation.RuntimeDefinedParameter("DoingA1", [String], $attrCollection)  
            $dynParam2 = new-object System.Management.Automation.RuntimeDefinedParameter("DoingA2", [String], $attrCollection)  
            
            # Parameter zum Dictionary hinzufügen
            $paramDic.Add("DoingA1", $dynParam1)  
            $paramDic.Add("DoingA2", $dynParam2)  
            return $paramDic
        }

        if ($B){
            $attr = new-object System.Management.Automation.ParameterAttribute
            $attr.ParameterSetName = "B"  
            $attr.Mandatory = $false
            $attrCollection.Add($attr)

            $dynParam1 = new-object System.Management.Automation.RuntimeDefinedParameter("DoingB1", [String], $attrCollection)  
            $dynParam2 = new-object System.Management.Automation.RuntimeDefinedParameter("DoingB2", [String], $attrCollection)  
            
            $paramDic.Add("DoingB1", $dynParam1)  
            $paramDic.Add("DoingB2", $dynParam2)  
            return $paramDic
        }

    }

    begin{}
    
    process{
        if ($A) {
            # So spricht man die dynamischen Parameter im Script an
            write-host $PSBoundParameters.DoingA1
            write-host $PSBoundParameters.DoingA2
        }
        if ($B) {
            write-host $PSBoundParameters.DoingB1
            write-host $PSBoundParameters.DoingB2
        }
    }
    
}

Test-Test -B -DoingB1 "Wert 1 von Set B" -DoingB2 "Wert 2 von Set B"  

back-to-topAnfänglich werden nur die zwei Switch-Parameter angezeigt
1a34f503c109ef65e5d38db750e5db99

back-to-topSobald dann ein Switch verwendet wurde werden nur die dem Parameterset zugehörigen Parameter angezeigt.

dcabb919757d38129a5d594d0b60d413

Noch wichtig zu erwähnen sei hierbei, dass du bei Verwendung von DynamicParam{} im Funktionsgerüst die vorgeschriebenen Bereiche wie begin{} , process{} , end{} für deinen Code nutzen musst.

Grüße Uwe
Mitglied: mayho33
mayho33 18.04.2014 um 16:07:04 Uhr
Goto Top
Hi Uwe!

WOW! DANKE!! Genau sowas versuche ich seit gestern Abend nonstop umzusetzen...mit nicht zufrieden stellendem Erfolg. Ich scheiterte immer am Definieren der Parameter als ValidationSet was wie ich jetzt erkenne erstens nicht geht und zweitens so viel übersichtlicher ist.

Wo erfährt man sowas??: System.Management.Automation.ParameterAttribute Wie? wo? in welchem Fall einsetzen?

MS dev lässt da viele Wünsche offen und die MSDN ist eher dürftig meiner Ansicht nach.

Bin dir echt dankbar! Du hast mir viele Stunden Sucherei erspart. In 3 Wochen soll ich das fertige Produkt präsentieren (Silent Un/Install via SCCM 2012 mit User-Noification, RC-Kontrolle, usw. und bin schon ein wenig gestresst obwohl schon fast fertig)

Danke nochmals! Gebe Rückmeldung mir Snippeds wenn ich fertig bin falls du Interesse hast

lg

mayho
Mitglied: colinardo
colinardo 18.04.2014 aktualisiert um 16:29:57 Uhr
Goto Top
Wo erfährt man sowas??
nun schon zum dritten...meine Links die ich poste mal etwas mehr beachten face-wink siehe Link aus dem ersten Kommentar:
http://technet.microsoft.com/en-us/library/dd347600.aspx
(fast nach ganz unten scrollen)

Die Referenzen reichen mir dafür völlig face-smile Die werden zu wenig gewürdigt. Man erfährt dort mehr als man so denkt ...

Viele Erfolg weiterhin und frohe Ostern.

Grüße Uwe
Mitglied: mayho33
mayho33 18.04.2014 um 17:04:17 Uhr
Goto Top
Ups!

Soooo weit unten war ich auf der Seite noch nie. WAs ich sah hat mir tlw. schon "gereicht"

ebenfalls schöne Ostern!

lg

mayho