So übergeben Sie boolesche Werte an einer Eingabeaufforderung an ein PowerShell-Skript

103

Ich muss ein PowerShell-Skript aus einer Batchdatei aufrufen. Eines der Argumente für das Skript ist ein boolescher Wert:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify $false

Der Befehl schlägt mit folgendem Fehler fehl:

Cannot process argument transformation on parameter 'Unify'. Cannot convert value "System.String" to type "System.Boolean", parameters of this type only accept booleans or numbers, use $true, $false, 1 or 0 instead.

At line:0 char:1
+  <<<< <br/>
+ CategoryInfo          : InvalidData: (:) [RunScript.ps1], ParentContainsErrorRecordException <br/>
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,RunScript.ps1

Ab sofort verwende ich eine Zeichenfolge zur booleschen Konvertierung in meinem Skript. Aber wie kann ich boolesche Argumente an PowerShell übergeben?

Mutelogan
quelle

Antworten:

57

Es scheint, dass Powershell.exe Skriptargumente nicht vollständig auswertet, wenn der -FileParameter verwendet wird. Insbesondere wird das $falseArgument ähnlich wie im folgenden Beispiel als Zeichenfolgenwert behandelt:

PS> function f( [bool]$b ) { $b }; f -b '$false'
f : Cannot process argument transformation on parameter 'b'. Cannot convert value 
"System.String" to type "System.Boolean", parameters of this type only accept 
booleans or numbers, use $true, $false, 1 or 0 instead.
At line:1 char:36
+ function f( [bool]$b ) { $b }; f -b <<<<  '$false'
    + CategoryInfo          : InvalidData: (:) [f], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,f

Anstatt zu verwenden, können -FileSie versuchen -Command, den Aufruf als Skript auszuwerten:

CMD> powershell.exe -NoProfile -Command .\RunScript.ps1 -Turn 1 -Unify $false
Turn: 1
Unify: False

Wie David vorschlägt, wäre die Verwendung eines switch-Arguments auch idiomatischer und würde den Aufruf vereinfachen, indem die Notwendigkeit beseitigt wird, einen booleschen Wert explizit zu übergeben:

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True
Kaiser XLII
quelle
6
Für diejenigen (wie ich), die den Parameter "-File" beibehalten müssen und nicht zu einem switch-Argument wechseln können, aber die Kontrolle über die gesendeten Zeichenfolgenwerte haben, besteht die einfachste Lösung darin, den Parameter in a zu konvertieren Boolescher Wert mit [System.Convert] :: ToBoolean ($ Unify); Die Zeichenfolgenwerte müssen dann "True" oder "False" sein.
Chris Haines
187

Eine klarere Verwendung könnte darin bestehen, stattdessen Schalterparameter zu verwenden. Dann würde nur das Vorhandensein des Unify-Parameters bedeuten, dass er festgelegt wurde.

Wie so:

param (
  [int] $Turn,
  [switch] $Unify
)
David Mohundro
quelle
21
Dies sollte die akzeptierte Antwort sein. Um die Diskussion voranzutreiben, können Sie einen Standardwert wie jeden anderen Parameter wie [switch] $Unify = $false
folgt
Ich habe diese Antwort übersehen, da ich sicher war, dass Boolean der richtige Weg war. Es ist nicht. Switch kapselt die Funktionalität des Booleschen Werts und stoppt diese Art von Fehlern: "Der Wert" False "kann nicht in" System.Management.Automation.ParameterAttribute "konvertiert werden. Die Switches haben bei mir funktioniert.
TinyRacoon
2
@MarioTacke Wenn Sie den Parameter switch beim Aufrufen des Skripts nicht angeben, wird er automatisch auf gesetzt $false. Es ist also nicht erforderlich, einen Standardwert explizit festzulegen.
DoubleDown
Dieser Vorschlag hat sehr gut funktioniert; konnte einen der Parameter von [bool] auf [switch] aktualisieren, wodurch ich das Argument erfolgreich über den Taskplaner übergeben konnte.
JustaDaKaje
12

Dies ist eine ältere Frage, aber in der PowerShell-Dokumentation gibt es tatsächlich eine Antwort darauf. Ich hatte das gleiche Problem und ausnahmsweise löste RTFM es tatsächlich. Fast.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe

In der Dokumentation für den Parameter -File heißt es: "In seltenen Fällen müssen Sie möglicherweise einen Booleschen Wert für einen Switch-Parameter angeben. Um einen Booleschen Wert für einen Switch-Parameter im Wert des File-Parameters anzugeben, geben Sie den Parameternamen und den Wert in an geschweifte Klammern wie die folgenden: -File. \ Get-Script.ps1 {-All: $ False} "

Ich musste es so schreiben:

PowerShell.Exe -File MyFile.ps1 {-SomeBoolParameter:False}

Also kein '$' vor der wahr / falsch-Anweisung, und das hat bei mir unter PowerShell 4.0 funktioniert

LarsWA
quelle
1
Ich danke Ihnen für das Teilen! Mein Problem perfekt gelöst.
Julia Schwarz
1
Der Inhalt des Links in der Antwort scheint sich geändert zu haben. Allerdings fand ich die Antwort hier
Slogmeister Extraordinaire
Aktueller Dokumentationslink about_powershell.exe alternativ nur angerufenpowershell -h .
Seth
Ich bin überrascht, dass diese umständliche Problemumgehung jemals funktioniert hat - in Windows PowerShell v5.1 (weder mit noch ohne Leading $). Beachten Sie außerdem, dass dies in PowerShell Core nicht mehr erforderlich ist . Ich habe darum gebeten, dass die Dokumentation korrigiert wird. siehe github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0
11

Versuchen Sie, den Typ Ihres Parameters auf Folgendes einzustellen [bool]:

param
(
    [int]$Turn = 0
    [bool]$Unity = $false
)

switch ($Unity)
{
    $true { "That was true."; break }
    default { "Whatever it was, it wasn't true."; break }
}

Dieses Beispiel Standardwert $Unityan , $falsewenn keine Eingabe vorgesehen ist.

Verwendung

.\RunScript.ps1 -Turn 1 -Unity $false
Filburt
quelle
1
Die Antwort von Kaiser XLII und Ihr Kommentar zum -FileParameter sollten jeden Aspekt der ursprünglichen Frage abdecken. Ich werde meine Antwort hinterlassen, da möglicherweise auch jemand meinen Hinweis zur Angabe eines Standardwerts nützlich findet.
Filburt
Gut gemacht, Filburt. Ihre Antwort hat mich veranlasst, mein Skript zu überprüfen, das bereits standardmäßig als erforderlichen Wert $ false angegeben wurde (das habe ich vor einigen Jahren geschrieben und alles vergessen) - daher muss ich nicht einmal den problematischen booleschen Parameter auf dem angeben Kommandozeile jetzt. Ausgezeichnet :)
Zeek2
5

Ich denke, der beste Weg, einen booleschen Wert als Parameter zu verwenden / festzulegen, besteht darin, ihn in Ihrem PS-Skript folgendermaßen zu verwenden:

Param(
    [Parameter(Mandatory=$false)][ValidateSet("true", "false")][string]$deployApp="false"   
)

$deployAppBool = $false
switch($deployPmCmParse.ToLower()) {
    "true" { $deployAppBool = $true }
    default { $deployAppBool = $false }
}

Jetzt können Sie es so verwenden:

.\myApp.ps1 -deployAppBool True
.\myApp.ps1 -deployAppBool TRUE
.\myApp.ps1 -deployAppBool true
.\myApp.ps1 -deployAppBool "true"
.\myApp.ps1 -deployAppBool false
#and etc...

In Argumenten von cmd können Sie also einen booleschen Wert als einfache Zeichenfolge übergeben :).

Drasius
quelle
2

In PowerShell können boolesche Parameter deklariert werden, indem ihr Typ vor ihrer Variablen angegeben wird.

    function GetWeb() {
             param([bool] $includeTags)
    ........
    ........
    }

Sie können einen Wert zuweisen, indem Sie $ true | übergeben $ false

    GetWeb -includeTags $true
Ahmed Ali
quelle
Nur die genannten Eingabeargumente explizit so zu übergeben, war ein Vergnügen. Danke Ahmed
Steve Taylor
0

Um die vorhandenen Antworten ab Windows PowerShell v5.1 / PowerShell Core 7.0.0-Vorschau 4 zusammenzufassen und zu ergänzen :

Die Antwort von David Mohundro weist zu Recht darauf hin, dass Sie anstelle von [bool]Parametern [switch]Parameter in PowerShell verwenden sollten , bei denen das Vorhandensein oder Nichtvorhandensein des Switch-Namens ( -Unifyangegeben vs. nicht angegeben) dessen Wert impliziert , wodurch das ursprüngliche Problem behoben wird.


Jedoch gelegentlich können Sie immer noch den Schalter übergeben müssen Wert ausdrücklich , vor allem , wenn Sie eine Befehlszeile sind die Konstruktion programmatisch :


In Powershell - Core , das ursprüngliche Problem (beschrieben in Emperor XLII Antwort ) wurde fixiert .

Das heißt, um $trueexplizit an einen [switch]Parameter mit dem Namen zu übergeben -Unify, können Sie jetzt schreiben:

pwsh -File .\RunScript.ps1 -Unify:$true  # !! ":" separates name and value, no space

Folgende Werte können verwendet werden: $false, false, $true, true, aber beachten Sie, dass vorbei 0oder 1tut nicht Arbeit.

Beachten Sie, wie der Switch-Name vom Wert mit getrennt wird :und zwischen den beiden kein Leerzeichen stehen darf .

Hinweis: Wenn Sie einen [bool]Parameter anstelle von a deklarieren [switch](was Sie normalerweise nicht tun sollten), müssen Sie dieselbe Syntax verwenden. Auch wenn -Unify $false es funktionieren sollte, funktioniert es derzeit nicht - siehe dieses GitHub-Problem .


In Windows PowerShell besteht das ursprüngliche Problem weiterhin und es ist unwahrscheinlich, dass es behoben wird, da Windows PowerShell nicht mehr aktiv entwickelt wird.

  • Die Problemumgehung in vorgeschlagen LarsWA Antwort - auch wenn es auf Basis des offiziellen Hilfethema zum Zeitpunkt des Schreibens - tut nicht Arbeit in v5.1

    • Dieses GitHub-Problem fordert die Korrektur der Dokumentation an und enthält außerdem einen Testbefehl, der die Ineffektivität der Problemumgehung anzeigt.
  • Die Verwendung von -Commandanstelle von -Fileist die einzige effektive Problemumgehung :

:: # From cmd.exe
powershell -Command "& .\RunScript.ps1 -Unify:$true" 

Mit übergeben -CommandSie effektiv einen Teil des PowerShell-Codes , der dann wie gewohnt ausgewertet wird - und innerhalb von PowerShell übergeben $trueund $falsefunktioniert (aber nicht true und false, wie jetzt auch akzeptiert -File).

Vorsichtsmaßnahmen :

  • Die Verwendung -Commandkann zu einer zusätzlichen Interpretation Ihrer Argumente führen, z. B. wenn sie $Zeichen enthalten . (mit -File, Argumente sind Literale ).

  • Die Verwendung -Commandkann zu einem anderen Exit-Code führen .

Einzelheiten finden Sie in dieser Antwort und in dieser Antwort .

mklement0
quelle
0

Ich hatte etwas Ähnliches, als ich ein Skript an eine Funktion mit dem Befehl invoke übergab. Ich habe den Befehl in einfachen Anführungszeichen anstelle von doppelten Anführungszeichen ausgeführt, da er dann zu einem Zeichenfolgenliteral wird.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';

Bbb
quelle
0

Das Ausführen von Powershell-Skripten unter Linux unter Bash führt zum gleichen Problem. Es wurde fast genauso gelöst wie die Antwort von LarsWA:

Arbeiten:

pwsh -f ./test.ps1 -bool:true

Funktioniert nicht:

pwsh -f ./test.ps1 -bool=1
pwsh -f ./test.ps1 -bool=true
pwsh -f ./test.ps1 -bool true
pwsh -f ./test.ps1 {-bool=true}
pwsh -f ./test.ps1 -bool=$true
pwsh -f ./test.ps1 -bool=\$true
pwsh -f ./test.ps1 -bool 1
pwsh -f ./test.ps1 -bool:1
JanRK
quelle
-3

Sie können auch 0für Falseoder 1für verwenden True. Es schlägt tatsächlich vor, dass in der Fehlermeldung:

Argumenttransformation für Parameter 'Unify' kann nicht verarbeitet werden. Wert kann nicht konvertieren , "System.String"um Typen "System.Boolean", Parameter dieser Art nur booleans oder Zahlen, die Verwendung akzeptieren $true, $false, 1 oder 0 statt.

Weitere Informationen finden Sie in diesem MSDN-Artikel zu Booleschen Werten und Operatoren .

Rahs
quelle
10
Das funktioniert nicht. Es erwartet eine Ganzzahl Nummer 1 oder 0, aber die Übergabe -Fileinterpretiert sie als Zeichenfolge und schlägt daher mit demselben Fehler fehl.
Erti-Chris Eelmaa
Diese Antwort ist falsch, da der Vorschlag nicht funktioniert
mjs