Jak przekazać wartości logiczne do skryptu programu PowerShell z wiersza polecenia

104

Muszę wywołać skrypt PowerShell z pliku wsadowego. Jednym z argumentów skryptu jest wartość logiczna:

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

Polecenie kończy się niepowodzeniem z następującym błędem:

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

Obecnie używam ciągu znaków do konwersji wartości boolowskiej w moim skrypcie. Ale jak mogę przekazać argumenty logiczne do programu PowerShell?

mutelogan
źródło

Odpowiedzi:

58

Wygląda na to, że program powershell.exe nie w pełni ocenia argumenty skryptu, gdy -Fileparametr jest używany. W szczególności $falseargument jest traktowany jako ciąg znaków, podobnie jak w poniższym przykładzie:

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

Zamiast używać -Filemożesz spróbować -Command, który oceni wywołanie jako skrypt:

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

Jak sugeruje David , użycie argumentu przełączającego byłoby również bardziej idiomatyczne, upraszczając wywołanie, eliminując potrzebę jawnego przekazywania wartości boolowskiej:

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True
Cesarz XLII
źródło
6
Dla tych (jak ja), którzy muszą zachować parametr „-File” i nie mogą zmienić argumentu przełączającego, ale mają kontrolę nad wysyłanymi wartościami ciągu, najprostszym rozwiązaniem jest przekonwertowanie parametru na boolean using [System.Convert] :: ToBoolean ($ Unify); wartości ciągu muszą mieć wtedy wartość „True” lub „False”.
Chris Haines
187

Bardziej przejrzystym zastosowaniem może być zamiast tego użycie parametrów przełącznika. Wtedy samo istnienie parametru Unify oznaczałoby, że został on ustawiony.

Tak jak to:

param (
  [int] $Turn,
  [switch] $Unify
)
David Mohundro
źródło
21
To powinna być akceptowana odpowiedź. Aby pogłębić dyskusję, możesz ustawić wartość domyślną, jak każdy inny parametr, na przykład:[switch] $Unify = $false
Mario Tacke
Przeoczyłem tę odpowiedź, ponieważ byłem pewien, że Boolean to najlepszy sposób. Nie jest. Przełącznik zawiera funkcjonalność wartości logicznej i zatrzymuje tego rodzaju błędy: „Nie można przekonwertować wartości„ False ”na typ„ System.Management.Automation.ParameterAttribute ”. Przełączniki działały dla mnie.
TinyRacoon
2
@MarioTacke Jeśli nie określisz parametru switch podczas wywoływania skryptu, zostanie on automatycznie ustawiony na $false. Nie ma więc potrzeby jawnego ustawiania wartości domyślnej.
doubleDown
Ta sugestia zadziałała bardzo dobrze; był w stanie zaktualizować jeden z parametrów z [bool] do [switch], co z powodzeniem umożliwiło mi przekazanie argumentu przez Harmonogram zadań.
JustaDaKaje
12

To jest starsze pytanie, ale w rzeczywistości jest na nie odpowiedź w dokumentacji programu PowerShell. Miałem ten sam problem i tym razem RTFM faktycznie go rozwiązał. Prawie.

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

Dokumentacja dotycząca parametru -File stwierdza, że ​​„W rzadkich przypadkach może być konieczne podanie wartości logicznej dla parametru przełącznika. Aby podać wartość logiczną parametru przełącznika w wartości parametru Plik, należy umieścić nazwę i wartość parametru w nawiasy klamrowe, takie jak: -File. \ Get-Script.ps1 {-All: $ False} "

Musiałem to napisać tak:

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

Więc nie ma znaku „$” przed stwierdzeniem prawda / fałsz i to zadziałało dla mnie w PowerShell 4.0

LarsWA
źródło
1
Dziękuję za udostępnienie! Doskonale rozwiązał mój problem.
Julia Schwarz
1
Wygląda na to, że odsyłacz w odpowiedzi miał zmienioną treść. Jednak znalazłem odpowiedź tutaj
Slogmeister Extraordinaire
Aktualne łącze do dokumentacji about_powershell.exe lub po prostu zadzwonić powershell -h.
Seth
Jestem zaskoczony, że to niezręczne obejście kiedykolwiek zadziałało - nie działa w programie Windows PowerShell w wersji 5.1 (ani z początkiem, ani bez niego $); Zauważ również, że nie jest to już konieczne w programie PowerShell Core . Poprosiłem o poprawienie dokumentacji; patrz github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0
11

Spróbuj ustawić typ parametru na [bool]:

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

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

Ten przykład domyślne $Unitydo$false jeśli nie jest warunkiem wejścia.

Stosowanie

.\RunScript.ps1 -Turn 1 -Unity $false
Filburt
źródło
1
Odpowiedź cesarza XLII i Twój komentarz dotyczący -Fileparametru powinny obejmować każdy aspekt pierwotnego pytania. Zostawię swoją odpowiedź, ponieważ ktoś może również uznać moją wskazówkę dotyczącą podania wartości domyślnej.
Filburt
Dobra robota Filburt. Twoja odpowiedź sprawiła, że ​​sprawdziłem mój skrypt, który już domyślnie określił jako wymaganą wartość $ false (pisałem to kilka lat temu i zapomniałem o tym) - więc nie muszę nawet określać problematycznego parametru boolowskiego na wiersz poleceń teraz. Doskonale :)
Zeek2
5

Myślę, że najlepszym sposobem na użycie / ustawienie wartości logicznej jako parametru jest użycie w skrypcie PS tak:

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

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

Więc teraz możesz go używać w ten sposób:

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

Więc w argumentach z cmd możesz przekazać wartość logiczną jako prosty ciąg :).

Drasius
źródło
2

W programie PowerShell parametry logiczne można zadeklarować, podając ich typ przed ich zmienną.

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

Możesz przypisać wartość, przekazując $ true | $ false

    GetWeb -includeTags $true
Ahmed Ali
źródło
Po prostu przekazanie nazwanych argumentów wejściowych jawnie w ten sposób zadziałało. Dzięki Ahmed
Steve Taylor
0

Aby podsumować i uzupełniać istniejące odpowiedzi , jak z Windows PowerShell v5.1 / PowerShell podstawowej 7.0.0-preview.4:

Odpowiedź Davida Mohundro słusznie wskazuje, że zamiast [bool]parametrów, których należy użyć[switch] parametrów w PowerShell , gdzie brak obecności w porównaniu z nazwą przełącznik ( -Unifyokreślony w porównaniu z nie określono) zakłada jej wartość , która sprawia, że oryginalny problem znika.


Jednak przy okazji możesz jeszcze zdać przełącznika wartość wyraźnie , szczególnie jeśli budowie wiersza polecenia programowo :


W programie PowerShell Core The oryginalny problem (opisany w odpowiedzi na cesarza XLII ) został ustalony .

To znaczy, aby $truejawnie przekazać [switch]parametr o nazwie -Unify, możesz teraz napisać:

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

Następujące wartości można stosować: $false, false,$true , true, ale pamiętać, że zdanie 0lub 1nie nie pracy.

Zwróć uwagę, jak nazwa przełącznika jest oddzielona od wartości :i nie może być między nimi żadnych spacji .

Uwaga: Jeśli deklarujesz [bool]parametr zamiast a [switch](czego generalnie nie powinieneś), musisz użyć tej samej składni; nawet jeśli-Unify $false powinno działać, obecnie nie - zobacz ten problem z GitHubem .


W Windows PowerShell , w oryginalnych problem nie ustąpi , i - biorąc pod uwagę, że Windows PowerShell nie jest już aktywnie rozwijany - jest mało prawdopodobne, aby uzyskać stałe.

  • Obejście sugerowane w odpowiedzi LarsWA - mimo że jest oparte na oficjalnym temacie pomocy w chwili pisania tego tekstu - nie działa w wersji 5.1

    • Ten problem z GitHubem wymaga poprawienia dokumentacji, a także zawiera polecenie testowe, które pokazuje nieskuteczność obejścia.
  • Używanie -Commandzamiast -Fileto jedyne skuteczne obejście :

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

Dzięki -Commandefektywnemu przekazaniu fragmentu kodu PowerShell , który jest następnie oceniany jak zwykle - i wewnątrz PowerShell przechodzi $truei $falsedziała (ale nie true i false, jak teraz jest również akceptowany z -File).

Ostrzeżenia :

  • Używanie -Commandmoże skutkować dodatkową interpretacją twoich argumentów, na przykład jeśli zawierają one $znaki. (z -Fileargumentami są literały ).

  • Użycie -Commandmoże skutkować innym kodem zakończenia .

Aby uzyskać szczegółowe informacje, zobacz tę odpowiedź i tę odpowiedź .

mklement0
źródło
0

Coś podobnego miałem podczas przekazywania skryptu do funkcji za pomocą polecenia invoke. Uruchomiłem polecenie w pojedynczych cudzysłowach zamiast w podwójnych cudzysłowach, ponieważ staje się wtedy literałem ciągu.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';

Bbb
źródło
0

Uruchamianie skryptów PowerShell na Linuksie z bash daje ten sam problem. Rozwiązałem to prawie tak samo, jak odpowiedź LarsWA:

Pracujący:

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

Nie działa:

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
źródło
-3

Możesz również użyć 0for Falselub 1for True. To faktycznie sugeruje, że w komunikacie o błędzie:

Nie można przetworzyć transformacji argumentów w parametrze „Unify”. Nie można przekonwertować wartości "System.String"na typ "System.Boolean", parametry tego typu przyjąć tylko wartości logicznych lub numerów, korzystanie $true, $false, 1 lub 0 zamiast.

Aby uzyskać więcej informacji, zapoznaj się z tym artykułem MSDN dotyczącym wartości logicznych i operatorów .

Rahs
źródło
10
To nie działa. Oczekuje liczby całkowitej 1 lub 0, ale przepuszczenie jej -Fileinterpretuje ją jako łańcuch, więc kończy się niepowodzeniem z tym samym błędem.
Erti-Chris Eelmaa
Ta odpowiedź jest błędna, ponieważ sugestia nie działa
mjs