Como passar valores booleanos para um script PowerShell a partir de um prompt de comando


103

Eu tenho que invocar um script PowerShell de um arquivo em lote. Um dos argumentos do script é um valor booleano:

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

O comando falha com o seguinte erro:

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

No momento, estou usando uma string para conversão booleana dentro do meu script. Mas como posso passar argumentos booleanos para PowerShell?

Respostas:


57

Parece que o powershell.exe não avalia totalmente os argumentos do script quando o -Fileparâmetro é usado. Em particular, o $falseargumento está sendo tratado como um valor de string, de maneira semelhante ao exemplo abaixo:

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

Em vez de usar, -Filevocê pode tentar -Command, o que avaliará a chamada como script:

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

Como David sugere, usar um argumento switch também seria mais idiomático, simplificando a chamada ao remover a necessidade de passar um valor booleano explicitamente:

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

6
Para aqueles (como eu) que precisam manter o parâmetro "-File" e não podem mudar para um argumento switch, mas têm controle sobre os valores de string que são enviados, então a solução mais simples é converter o parâmetro em um booleano usando [System.Convert] :: ToBoolean ($ Unify); os valores da string devem ser "True" ou "False".
Chris Haines,

187

Um uso mais claro pode ser usar parâmetros de switch. Então, apenas a existência do parâmetro Unify significaria que ele foi definido.

Igual a:

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

21
Esta deve ser a resposta aceita. Para aprofundar a discussão, você pode definir um valor padrão como qualquer outro parâmetro, como:[switch] $Unify = $false
Mario Tacke

Esqueci essa resposta, pois tinha certeza de que Boolean era o caminho a percorrer. Não é. O switch encapsula a funcionalidade do booleano e interrompe este tipo de erro: "Não é possível converter o valor" False "para o tipo" System.Management.Automation.ParameterAttribute ". Os switches funcionaram para mim.
TinyRacoon de

2
@MarioTacke Se você não especificar o parâmetro switch ao invocar o script, ele será automaticamente definido como $false. Portanto, não há necessidade de definir explicitamente um valor padrão.
DoubleDown

Essa sugestão funcionou muito bem; foi capaz de atualizar um dos parâmetros de [bool] para [switch] e isso me permitiu passar o argumento por meio do Agendador de tarefas.
JustaDaKaje

12

Esta é uma pergunta mais antiga, mas na verdade há uma resposta para ela na documentação do PowerShell. Eu tive o mesmo problema, e desta vez o RTFM realmente o resolveu. Quase.

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

A documentação para o parâmetro -File afirma que "Em casos raros, pode ser necessário fornecer um valor booleano para um parâmetro switch. Para fornecer um valor booleano para um parâmetro switch no valor do parâmetro File, coloque o nome do parâmetro e o valor em chaves, como as seguintes: -File. \ Get-Script.ps1 {-All: $ False} "

Eu tive que escrever assim:

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

Portanto, sem '$' antes da declaração verdadeiro / falso, e funcionou para mim, no PowerShell 4.0


1
Obrigado por compartilhar! Resolveu meu problema perfeitamente.
Julia Schwarz

1
O link da resposta parece ter seu conteúdo alterado. No entanto, encontrei a resposta aqui
Slogmeister Extraordinaire

Link da documentação atual about_powershell.exe, alternativamente, apenas rung powershell -h.
Seth

Estou surpreso que essa estranha solução alternativa já funcionou - não funciona no Windows PowerShell v5.1 (nem com nem sem guia $); também observe que não é mais necessário no PowerShell Core . Pedi que a documentação seja corrigida; consulte github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0

11

Tente definir o tipo de seu parâmetro para [bool]:

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

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

Este exemplo padrões $Unitypara $falsese nenhuma entrada é fornecida.

Uso

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

1
A resposta do Imperador XLII e seu comentário sobre o -Fileparâmetro devem cobrir todos os aspectos da pergunta original. Vou deixar minha resposta porque alguém também pode achar útil minha dica sobre como fornecer um valor padrão.
Filburt de

Filburt bem fechado. Sua resposta me fez verificar meu script, que já tem o padrão especificado como o valor obrigatório $ false (eu escrevi isso há vários anos e tinha esquecido tudo sobre ele) - então nem preciso especificar o parâmetro booleano problemático no linha de comando agora. Excelente :)
Zeek2

5

Eu acho que a melhor maneira de usar / definir o valor booleano como parâmetro é usar em seu script PS assim:

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

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

Então agora você pode usá-lo assim:

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

Portanto, em argumentos de cmd, você pode passar o valor booleano como string simples :).


2

No PowerShell, os parâmetros booleanos podem ser declarados mencionando seu tipo antes de sua variável.

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

Você pode atribuir valor passando $ true | $ false

    GetWeb -includeTags $true

Apenas passar os argumentos de entrada nomeados explicitamente assim funcionou muito bem. Obrigado Ahmed
Steve Taylor

0

Para resumir e complementar as respostas existentes , a partir do Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

A resposta de David Mohundro aponta corretamente que, em vez de [bool]parâmetros, você deve usar [switch]parâmetros no PowerShell , onde a presença vs. ausência do nome do switch ( -Unifyespecificado vs. não especificado) implica seu valor , o que faz com que o problema original desapareça.


No entanto, às vezes você ainda pode precisar passar o valor de switch explicitamente , especialmente se você estiver construindo uma linha de comando programaticamente :


No PowerShell Core , o problema original (descrito na resposta do Imperador XLII ) foi corrigido .

Ou seja, para passar $trueexplicitamente para um [switch]parâmetro denominado, -Unifyagora você pode escrever:

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

Os seguintes valores podem ser usados: $false, false, $true, true, mas nota que passa 0ou 1faz não trabalho.

Observe como o nome do switch é separado do valor com :e não deve haver nenhum espaço em branco entre os dois.

Nota: Se você declarar um [bool]parâmetro em vez de [switch](o que geralmente não deve ser feito), deverá usar a mesma sintaxe; embora -Unify $false deva funcionar, atualmente não funciona - veja este problema do GitHub .


No Windows PowerShell , o problema original persiste e - visto que o Windows PowerShell não é mais desenvolvido ativamente - é improvável que seja corrigido.

  • A solução alternativa sugerida na resposta do LarsWA - embora seja baseada no tópico de ajuda oficial no momento da redação deste documento - não funciona na v5.1

    • Este problema do GitHub pede que a documentação seja corrigida e também fornece um comando de teste que mostra a ineficácia da solução alternativa.
  • Usar em -Commandvez de -Fileé a única solução alternativa eficaz :

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

Com -Commandvocê está efetivamente passando uma parte do código do PowerShell , que é então avaliado como de costume - e dentro do PowerShell passando $truee $falsefunciona (mas não true e false, como agora também é aceito com -File).

Advertências :

  • Usar -Commandpode resultar em uma interpretação adicional de seus argumentos, como se eles contivessem $chars. (com -File, os argumentos são literais ).

  • O uso -Commandpode resultar em um código de saída diferente .

Para detalhes, veja esta resposta e esta resposta .


0

Tive algo semelhante ao passar um script para uma função com invoke-command. Executei o comando entre aspas simples em vez de aspas duplas, porque então ele se torna um literal de string.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';


0

A execução de scripts do PowerShell no Linux a partir do bash apresenta o mesmo problema. Resolvido quase da mesma forma que a resposta de LarsWA:

Trabalhando:

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

Não está funcionando:

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

Você também pode usar 0para Falseou 1para True. Na verdade, sugere que na mensagem de erro:

Não é possível processar a transformação do argumento no parâmetro 'Unificar'. Não é possível converter o valor "System.String"com o tipo "System.Boolean", parâmetros deste tipo só aceitam booleans ou números, utilização $true, $false, 1 ou 0 em vez.

Para obter mais informações, consulte este artigo do MSDN sobre Boolean Values ​​and Operators .


10
Isso não funciona. Ele está esperando o número inteiro 1 ou 0, mas transmiti-lo -Fileinterpreta como string, portanto, falha com o mesmo erro.
Erti-Chris Eelmaa

Esta resposta está errada, pois a sugestão não funciona
mjs
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.