Як передавати булеві значення в скрипт 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.