Come passare valori booleani a uno script di PowerShell da un prompt dei comandi


103

Devo richiamare uno script PowerShell da un file batch. Uno degli argomenti dello script è un valore booleano:

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

Il comando non riesce con il seguente errore:

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

A partire da ora sto usando una stringa per la conversione booleana all'interno del mio script. Ma come posso passare argomenti booleani a PowerShell?

Risposte:


57

Sembra che powershell.exe non valuti completamente gli argomenti dello script quando -Fileviene utilizzato il parametro. In particolare, l' $falseargomento viene trattato come un valore stringa, in modo simile all'esempio seguente:

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

Invece di usare -Filepotresti provare -Command, che valuterà la chiamata come script:

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

Come suggerisce David , l'utilizzo di un argomento switch sarebbe anche più idiomatico, semplificando la chiamata eliminando la necessità di passare esplicitamente un valore booleano:

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True

6
Per quelli (come me) che devono mantenere il parametro "-File" e non possono passare a un argomento switch, ma hanno il controllo sui valori di stringa inviati, la soluzione più semplice è convertire il parametro in un booleano utilizzando [System.Convert] :: ToBoolean ($ Unify); i valori della stringa devono quindi essere "True" o "False".
Chris Haines

187

Un utilizzo più chiaro potrebbe essere quello di utilizzare invece i parametri di commutazione. Quindi, solo l'esistenza del parametro Unify significherebbe che è stato impostato.

Così:

param (
  [int] $Turn,
  [switch] $Unify
)

21
Questa dovrebbe essere la risposta accettata. Per approfondire la discussione, puoi impostare un valore predefinito come qualsiasi altro parametro in questo modo:[switch] $Unify = $false
Mario Tacke

Ho trascurato questa risposta, poiché ero sicuro che Boolean fosse la strada da percorrere. Non è. Switch incapsula la funzionalità del booleano e blocca questo tipo di errori: "Impossibile convertire il valore" False "nel tipo" System.Management.Automation.ParameterAttribute ". Gli interruttori hanno funzionato per me.
TinyRacoon

2
@MarioTacke Se non si specifica il parametro switch quando si richiama lo script, viene automaticamente impostato su $false. Quindi non è necessario impostare esplicitamente un valore predefinito.
Doppio in calo il

Questo suggerimento ha funzionato molto bene; è stato in grado di aggiornare uno dei parametri da [bool] a [switch] e questo mi ha permesso di passare l'argomento tramite Task Scheduler.
JustaDaKaje

12

Questa è una domanda precedente, ma in realtà c'è una risposta nella documentazione di PowerShell. Ho avuto lo stesso problema e per una volta RTFM lo ha effettivamente risolto. Quasi.

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

La documentazione per il parametro -File afferma che "In rari casi, potrebbe essere necessario fornire un valore booleano per un parametro switch. Per fornire un valore booleano per un parametro switch nel valore del parametro File, racchiudi il nome e il valore del parametro in parentesi graffe, come le seguenti: -File. \ Get-Script.ps1 {-All: $ False} "

Ho dovuto scriverlo così:

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

Quindi nessun '$' prima della dichiarazione vero / falso, e per me ha funzionato, su PowerShell 4.0


1
Grazie per aver condiviso! Ha risolto perfettamente il mio problema.
Julia Schwarz

1
Il collegamento nella risposta sembra aver cambiato il suo contenuto. Tuttavia, ho trovato la risposta qui
Slogmeister Extraordinaire

Il collegamento alla documentazione corrente about_powershell.exe in alternativa è appena suonatopowershell -h .
Seth

Sono sorpreso che questa imbarazzante soluzione alternativa abbia mai funzionato - non è in Windows PowerShell v5.1 (né con né senza un inizio $); si noti inoltre che non è più necessario in PowerShell Core . Ho chiesto di correggere la documentazione; vedi github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0

11

Prova a impostare il tipo di parametro su [bool]:

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

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

Il valore predefinito $Unitydi questo esempio è $falsese non viene fornito alcun input.

uso

.\RunScript.ps1 -Turn 1 -Unity $false

1
La risposta di Emperor XLII e il tuo commento in merito al -Fileparametro dovrebbero coprire ogni aspetto della domanda originale. Lascio la mia risposta perché qualcuno potrebbe anche trovare utile il mio suggerimento sul fornire un valore predefinito.
Filburt

Ben fatto Filburt. La tua risposta mi ha fatto controllare il mio script, che ha già il valore predefinito specificato come valore richiesto $ false (l'ho scritto diversi anni fa e mi ero dimenticato tutto) - quindi non devo nemmeno specificare il parametro booleano problematico sul riga di comando ora. Eccellente :)
Zeek2

5

Penso che il modo migliore per usare / impostare il valore booleano come parametro sia usarlo nel tuo script PS in questo modo:

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

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

Quindi ora puoi usarlo in questo modo:

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

Quindi negli argomenti da cmd puoi passare il valore booleano come semplice stringa :).


2

In PowerShell, i parametri booleani possono essere dichiarati menzionando il loro tipo prima della loro variabile.

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

È possibile assegnare un valore passando $ true | $ false

    GetWeb -includeTags $true

Il solo passaggio esplicito degli argomenti di input con nome in questo modo ha funzionato a meraviglia. Grazie Ahmed
Steve Taylor,

0

Per riassumere e completare le risposte esistenti , a partire da Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

La risposta di David Mohundro giustamente sottolinea che al posto dei [bool]parametri dovresti usare i [switch]parametri in PowerShell , dove la presenza o l'assenza del nome dello switch ( -Unifyspecificato o non specificato) implica il suo valore , il che fa scomparire il problema originale.


Tuttavia, a volte potresti ancora dover passare il valore dello switch in modo esplicito , in particolare se stai costruendo una riga di comando a livello di codice :


In PowerShell Core , il problema originale (descritto nella risposta di Emperor XLII ) è stato risolto .

Cioè, per passare $trueesplicitamente a un [switch]parametro denominato -Unifyora puoi scrivere:

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

I seguenti valori possono essere utilizzati: $false, false, $true, true, ma nota che passa 0o 1fa no lavoro.

Nota come il nome dello switch è separato dal valore con :e non devono esserci spazi vuoti tra i due.

Nota: se dichiari un [bool]parametro invece di un [switch](cosa che generalmente non dovresti), devi usare la stessa sintassi; anche se -Unify $false dovrebbe funzionare, attualmente non funziona - vedi questo problema di GitHub .


In Windows PowerShell , il problema originale persiste e, dato che Windows PowerShell non è più sviluppato attivamente, è improbabile che venga risolto.

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

Con -Commandstai effettivamente passando un pezzo di codice PowerShell , che viene quindi valutato come al solito - e all'interno di PowerShell passa $truee $falsefunziona (ma non true e false, come ora anche accettato con -File).

Avvertenze :

  • L'utilizzo -Commandpuò comportare un'ulteriore interpretazione degli argomenti, ad esempio se contengono $caratteri. (con -File, gli argomenti sono letterali ).

  • L'utilizzo -Commandpuò comportare un codice di uscita diverso .

Per i dettagli, vedere questa risposta e questa risposta .


0

Ho avuto qualcosa di simile quando ho passato uno script a una funzione con invoke-command. Ho eseguito il comando tra virgolette singole invece che virgolette doppie, perché poi diventa una stringa letterale.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';


0

L'esecuzione di script PowerShell su Linux da bash dà lo stesso problema. Risolto quasi come la risposta di LarsWA:

Lavorando:

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

Non funziona:

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

-3

Puoi anche usare 0per Falseo 1per True. In realtà suggerisce che nel messaggio di errore:

Impossibile elaborare la trasformazione dell'argomento sul parametro "Unify". Non è possibile convertire il valore "System.String"di tipo "System.Boolean", i parametri di questo tipo accettano solo booleani o numeri, uso $true, $false, 1 o 0, invece.

Per ulteriori informazioni, consulta questo articolo di MSDN su valori e operatori booleani .


10
Non funziona. Si aspetta il numero intero 1 o 0, ma passandolo lo -Fileinterpreta come stringa, quindi fallisce con lo stesso errore.
Erti-Chris Eelmaa

Questa risposta è sbagliata, poiché il suggerimento non funziona
mjs
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.