วิธีส่งค่าบูลีนไปยังสคริปต์ 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

ดังที่เดวิดแนะนำการใช้อาร์กิวเมนต์สวิตช์จะเป็นสำนวนมากกว่าทำให้การโทรง่ายขึ้นโดยการลบความจำเป็นในการส่งค่าบูลีนอย่างชัดเจน:

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

6
สำหรับผู้ที่ (เช่นฉัน) ที่ต้องเก็บพารามิเตอร์ "-File" ไว้และไม่สามารถเปลี่ยนเป็นอาร์กิวเมนต์ของสวิตช์ได้ แต่มีการควบคุมค่าสตริงที่ส่งไปวิธีแก้ปัญหาที่ง่ายที่สุดคือการแปลงพารามิเตอร์เป็น บูลีนโดยใช้ [System.Convert] :: ToBoolean ($ Unify); จากนั้นค่าสตริงจะต้องเป็น "จริง" หรือ "เท็จ"
Chris Haines

187

การใช้งานที่ชัดเจนยิ่งขึ้นอาจเป็นการใช้พารามิเตอร์สวิตช์แทน จากนั้นการมีอยู่ของพารามิเตอร์ Unify ก็หมายความว่ามีการตั้งค่า

ชอบมาก:

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

21
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ หากต้องการสนทนาเพิ่มเติมคุณสามารถตั้งค่าเริ่มต้นเหมือนกับพารามิเตอร์อื่น ๆ ได้ดังนี้:[switch] $Unify = $false
Mario Tacke

ฉันมองข้ามคำตอบนี้ไปเพราะฉันแน่ใจว่าบูลีนคือหนทางที่จะไป มันไม่ใช่. สวิตช์สรุปการทำงานของบูลีนและหยุดข้อผิดพลาดประเภทนี้: "ไม่สามารถแปลงค่า" เท็จ "เป็นพิมพ์" System.Management.Automation.ParameterAttribute "สวิตช์ทำงานให้ฉัน
TinyRacoon

2
@MarioTacke หากคุณไม่ได้ระบุพารามิเตอร์สวิตช์เมื่อเรียกใช้สคริปต์จะถูกตั้งค่าเป็น$false. ดังนั้นจึงไม่จำเป็นต้องตั้งค่าเริ่มต้นอย่างชัดเจน
doubleDown

ข้อเสนอแนะนี้ใช้ได้ผลดีมาก สามารถอัปเดตพารามิเตอร์หนึ่งจาก [บูล] เป็น [สวิตช์] และสิ่งนี้ทำให้ฉันสามารถส่งผ่านอาร์กิวเมนต์ผ่าน Task Scheduler ได้สำเร็จ
JustaDaKaje

12

นี่เป็นคำถามที่เก่ากว่า แต่มีคำตอบอยู่ในเอกสาร PowerShell ฉันมีปัญหาเดียวกันและเมื่อ RTFM แก้ไขได้จริง เกือบ.

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

เอกสารประกอบสำหรับพารามิเตอร์ -File ระบุว่า "ในบางกรณีที่เกิดขึ้นไม่บ่อยคุณอาจต้องระบุค่าบูลีนสำหรับพารามิเตอร์สวิตช์ในการระบุค่าบูลีนสำหรับพารามิเตอร์สวิตช์ในค่าของพารามิเตอร์ File ให้ใส่ชื่อพารามิเตอร์และค่าใน วงเล็บปีกกาดังต่อไปนี้: -File. \ Get-Script.ps1 {-All: $ False} "

ฉันต้องเขียนแบบนี้:

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

ดังนั้นจึงไม่มี '$' ก่อนคำสั่งจริง / เท็จและนั่นใช้ได้ผลสำหรับฉันใน PowerShell 4.0


1
ขอบคุณสำหรับการแชร์! แก้ไขปัญหาของฉันได้อย่างสมบูรณ์แบบ
Julia Schwarz

1
ดูเหมือนว่าลิงก์ในคำตอบจะมีการเปลี่ยนแปลงเนื้อหา อย่างไรก็ตามฉันพบคำตอบที่นี่
Slogmeister Extraordinaire

การเชื่อมโยงเอกสารปัจจุบันabout_powershell.exepowershell -hผลัดเพียงรุ่ง
Seth

ฉันแปลกใจที่วิธีแก้ปัญหาที่น่าอึดอัดใจนี้ไม่ได้ผล - มันไม่ได้อยู่ใน Windows PowerShell v5.1 (ไม่ว่าจะมีหรือไม่มีแกนนำ$) นอกจากนี้ยังทราบว่ามันไม่จำเป็นอีกต่อไปใน PowerShell หลัก ฉันขอเอกสารที่จะแก้ไข ดู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
คำตอบของ Emperor XLII และความคิดเห็นของคุณเกี่ยวกับ-Fileพารามิเตอร์ควรครอบคลุมทุกแง่มุมของคำถามเดิม ฉันจะทิ้งคำตอบไว้เพราะอาจมีคนพบว่าคำแนะนำของฉันในการให้ค่าเริ่มต้นมีประโยชน์
Filburt

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 | $ เท็จ

    GetWeb -includeTags $true

เพียงแค่ส่งอาร์กิวเมนต์อินพุตที่ระบุชื่ออย่างชัดเจนเช่นนั้นก็ใช้ได้ผล ขอบคุณ Ahmed
Steve Taylor

0

เพื่อสรุปและเสริมคำตอบที่มีอยู่ใน Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

คำตอบของ David Mohundroชี้ให้เห็นอย่างถูกต้องว่าแทนที่จะใช้[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]พารามิเตอร์แทน a [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

การรันสคริปต์ 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"พารามิเตอร์ประเภทนี้จะยอมรับเฉพาะ booleans หรือตัวเลขการใช้งาน$true, $false, 1 หรือ 0 แทน

สำหรับข้อมูลเพิ่มเติมโปรดดูบทความ MSDN นี้ค่าบูลีนและผู้ประกอบการ


10
ที่ไม่ได้ผล มันคาดหวังว่าเลขจำนวนเต็ม 1 หรือ 0 แต่การส่งผ่าน-Fileตีความเป็นสตริงจึงล้มเหลวด้วยข้อผิดพลาดเดียวกัน
Erti-Chris Eelmaa

คำตอบนี้ไม่ถูกต้องเนื่องจากข้อเสนอแนะใช้ไม่ได้
mjs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.