Как передать логические значения в сценарий 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

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.


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может привести к другому коду выхода .

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


0

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


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

-3

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

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

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


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

Этот ответ неверен, поскольку предложение не работает
— mjs
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.