Як передавати булеві значення в скрипт PowerShell з командного рядка


103

Я повинен викликати скрипт 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?

Відповіді:


57

Видається, що 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

Як пропонує Девід , використання аргументу перемикання також було б більш ідіоматичним, спростивши виклик, усунувши необхідність явно передавати булеве значення:

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

6
Для тих (як я), які мають зберегти параметр "-File" і не можуть змінити аргумент перемикача, але мають контроль над надісланими рядковими значеннями, тоді найпростішим рішенням є перетворення параметра в булева за допомогою [System.Convert] :: ToBoolean ($ Unify); значення рядка повинні бути "True" або "False".
Кріс Хейнс

187

Більш чітке використання може бути замість цього використовувати параметри комутатора. Тоді саме існування параметра Unify означало б його встановлення.

Так:

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

21
Це має бути прийнятою відповіддю. Для подальшого обговорення, ви можете встановити значення за замовчуванням , як і будь-якого іншого параметр , як так:[switch] $Unify = $false
Маріо Так

Я не помітив цієї відповіді, тому що був впевнений, що Булевом буде шлях. Це не. Перемикання інкапсулює функціональність булевого типу та зупиняє такі помилки: "Неможливо перетворити значення" Неправильне "у тип" System.Management.Automation.ParameterAttribute ". Комутатори працювали для мене.
TinyRacoon

2
@MarioTacke Якщо не викликати параметр перемикача при виклику сценарію, він автоматично встановлюється на $false. Тому не потрібно чітко встановлювати значення за замовчуванням.
подвійнеDown

Ця пропозиція спрацювала дуже добре; вдалося оновити один із параметрів від [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}

Тож ніяких "$" перед істинним / хибним твердженням, і це працювало для мене, на PowerShell 4.0


1
Дякую, що поділились! Вирішили мою проблему ідеально.
Джулія Шварц

1
Здається, посилання у відповіді змінило її зміст. Однак я знайшов відповідь тут
Slogmeister Extraordinaire

Поточна посилання на документацію about_powershell.exe, або просто передзвонітьpowershell -h .
Сет

Я здивований, що цей незручний спосіб коли-небудь спрацював - його немає в Windows PowerShell v5.1 (ні з провідним, ні без провідного $); також зауважте, що в PowerShell Core це більше не потрібно . Я попросив виправити документацію; дивись github.com/MicrosoftDocs/PowerShell-Docs/isissue/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параметра повинні охоплювати кожен аспект оригінального питання. Я залишу свою відповідь, тому що хтось може також вважати корисним мій натяк на надання значення за замовчуванням.
Фільбурт

Молодці Фільбурт. Ваша відповідь змусила мене перевірити мій сценарій, який уже за замовчуванням вказав необхідне значення $ 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

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


0

Запуск скриптів повноважень на 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. Це фактично говорить про те, що в повідомленні про помилку:

Неможливо обробити перетворення аргументу параметром "Уніфікувати". Неможливо конвертувати "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.