Как передать логические значения в сценарий PowerShell из командной строки

104

Мне нужно вызвать сценарий PowerShell из командного файла. Один из аргументов скрипта - логическое значение:

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

Команда не выполняется со следующей ошибкой:

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

На данный момент я использую преобразование строки в логическое значение внутри своего скрипта. Но как передать в PowerShell логические аргументы?

мутелоган
источник

Ответы:

58

Похоже, что powershell.exe не полностью оценивает аргументы сценария при использовании -Fileпараметра. В частности, $falseаргумент обрабатывается как строковое значение аналогично приведенному ниже примеру:

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

Вместо использования -Fileвы можете попробовать -Command, который будет оценивать вызов как сценарий:

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

Как предполагает Дэвид , использование аргумента switch также было бы более идиоматичным, упростив вызов, исключив необходимость явно передавать логическое значение:

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True
Император XLII
источник
6
Для тех (таких как я), которые должны сохранить параметр «-File» и не могут изменить аргумент переключателя, но имеют контроль над отправляемыми строковыми значениями, самое простое решение - преобразовать параметр в логическое значение using [System.Convert] :: ToBoolean ($ Unify); тогда строковые значения должны быть «Истина» или «Ложь».
Крис Хейнс
187

Более понятным вариантом может быть использование вместо этого параметров переключения. Тогда только наличие параметра Unify будет означать, что он установлен.

Вот так:

param (
  [int] $Turn,
  [switch] $Unify
)
Дэвид Мохундро
источник
21
Это должен быть принятый ответ. Чтобы продолжить обсуждение, вы можете установить значение по умолчанию, как и любой другой параметр, например:[switch] $Unify = $false
Марио Таке,
Я пропустил этот ответ, так как был уверен, что Boolean - это лучший вариант. Это не. Switch инкапсулирует функциональность логического значения и останавливает такие ошибки: «Невозможно преобразовать значение« False »в тип« System.Management.Automation.ParameterAttribute ». У меня переключатели сработали.
TinyRacoon
2
@MarioTacke Если вы не укажете параметр переключателя при вызове скрипта, он будет автоматически установлен на $false. Таким образом, нет необходимости явно устанавливать значение по умолчанию.
doubleDown
Это предложение сработало очень хорошо; смог обновить один из параметров с [bool] до [switch], и это успешно позволило мне передать аргумент через планировщик задач.
JustaDaKaje
12

Это более старый вопрос, но на самом деле ответ на него есть в документации PowerShell. У меня была та же проблема, и на этот раз RTFM действительно ее решил. Почти.

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

В документации для параметра -File указано, что «В редких случаях может потребоваться предоставить логическое значение для параметра переключателя. Чтобы предоставить логическое значение для параметра переключателя в значении параметра файла, заключите имя параметра и значение в фигурные скобки, например: -File. \ Get-Script.ps1 {-All: $ False} "

Пришлось написать так:

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

Итак, перед утверждением true / false нет символа «$», и это сработало для меня в PowerShell 4.0.

LarsWA
источник
1
Спасибо, что поделились! Решил мою проблему отлично.
Юлия Шварц
1
Похоже, что содержание ссылки в ответе изменилось. Тем не менее, я нашел ответ здесь
Slogmeister Extraordinaire
Текущая ссылка на документацию about_powershell.exe в качестве альтернативы просто звонит powershell -h.
Сет
Я удивлен, что этот неудобный обходной путь когда-либо работал - его нет в Windows PowerShell v5.1 (ни с ведущим, ни без него $); также обратите внимание, что в PowerShell Core он больше не нужен . Я попросил исправить документацию; см. github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0
11

Попробуйте установить тип вашего параметра на [bool]:

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

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

В этом примере по умолчанию $Unityв $falseслучае не предусмотрено никакого входа.

использование

.\RunScript.ps1 -Turn 1 -Unity $false
Филбурт
источник
1
Ответ императора XLII и ваш комментарий к нему относительно -Fileпараметра должны охватывать все аспекты исходного вопроса. Я оставлю свой ответ, потому что кто-то может также найти мою подсказку о предоставлении значения по умолчанию.
Filburt
Молодец Филбурт. Ваш ответ заставил меня проверить свой скрипт, в котором по умолчанию уже указано требуемое значение $ false (я написал это несколько лет назад и забыл об этом), поэтому мне даже не нужно указывать проблемный логический параметр в командная строка сейчас. Отлично :)
Zeek2
5

Я думаю, что лучший способ использовать / установить логическое значение в качестве параметра - использовать в вашем скрипте PS это так:

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

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

Итак, теперь вы можете использовать это так:

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

Таким образом, в аргументах из cmd вы можете передать логическое значение как простую строку :).

Дразиус
источник
2

В PowerShell логические параметры можно объявить, указав их тип перед их переменной.

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

Вы можете присвоить значение, передав $ true | $ false

    GetWeb -includeTags $true
Ахмед Али
источник
Простая передача названных входных аргументов в явном виде сработала. Спасибо Ахмед
Стив Тейлор
0

Для того, чтобы обобщить и дополнить существующие ответы , начиная с Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

Ответ Дэвида Мохундро справедливо указывает на то, что вместо [bool]параметров вы должны использовать [switch]параметры в PowerShell , где наличие или отсутствие имени переключателя ( -Unifyуказанного или не указанного) подразумевает его значение , что устраняет исходную проблему.


Тем не менее, в некоторых случаях вам может потребоваться передать переключатель значение явно , особенно если вы построения командной строки программно :


В PowerShell ядро , то исходная задача (описанный в ответ императора XLII в ) была фиксированной .

То есть, чтобы $trueявно перейти к [switch]параметру с именем -Unify, теперь вы можете написать:

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

Могут быть использованы следующие значения: $false, false, $true, true, но заметьте , что передача 0или 1же не работать.

Обратите внимание, как имя переключателя отделяется от значения с помощью :и между ними не должно быть пробелов .

Примечание. Если вы объявляете [bool]параметр вместо [switch](чего обычно не следует), вы должны использовать тот же синтаксис; хотя -Unify $false должно работать, в настоящее время это не так - см. эту проблему на GitHub .


В Windows PowerShell , в оригинальной проблема не решена , и - учитывая , что Windows PowerShell больше не активно развивается - вряд ли исправлена.

  • Обходной путь, предложенный в ответе LarsWA - хотя он основан на официальной теме справки на момент написания этой статьи - не работает в v5.1

    • Эта проблема GitHub требует исправления документации, а также предоставляет тестовую команду, которая показывает неэффективность обходного пути.
  • Использование -Commandвместо -File- единственный эффективный обходной путь :

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

Таким образом, -Commandвы эффективно передаете фрагмент кода PowerShell , который затем оценивается как обычно - а внутри PowerShell передает $trueи $falseработает (но не true и false, как теперь принято с -File).

Предостережения :

  • Использование -Commandможет привести к дополнительной интерпретации ваших аргументов, например, если они содержат $символы. (с -Fileаргументами являются литералами ).

  • Использование -Commandможет привести к другому коду выхода .

Подробнее см. Этот ответ и этот ответ .

mklement0
источник
0

У меня было нечто подобное при передаче скрипта функции с помощью invoke-command. Я выполнил команду в одинарных кавычках вместо двойных, потому что тогда она становится строковым литералом.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';

BBB
источник
0

Выполнение сценариев powershell в Linux из bash дает ту же проблему. Решил это почти так же, как ответ LarsWA:

Работает:

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

Не работает:

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
источник
-3

Вы также можете использовать 0для Falseили 1для True. На самом деле это говорит о том, что в сообщении об ошибке:

Невозможно обработать преобразование аргумента для параметра «Unify». Невозможно преобразовать значение "System.String"в тип "System.Boolean", параметры этого типа принимают только булевы или цифры, использование $true, $false, 1 или 0 вместо.

Для получения дополнительной информации ознакомьтесь с этой статьей MSDN о логических значениях и операторах .

Rahs
источник
10
Это не работает. Ожидается целое число 1 или 0, но его передача -Fileинтерпретирует его как строку, поэтому происходит сбой с той же ошибкой.
Эрти-Крис Элмаа,
Этот ответ неверен, поскольку предложение не работает
mjs