Cara meneruskan nilai boolean ke skrip PowerShell dari prompt perintah

103

Saya harus menjalankan skrip PowerShell dari file batch. Salah satu argumen untuk skrip adalah nilai boolean:

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

Perintah gagal dengan kesalahan berikut:

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

Sampai sekarang saya menggunakan konversi string ke boolean di dalam skrip saya. Tapi bagaimana saya bisa meneruskan argumen boolean ke PowerShell?

mutelogan
sumber

Jawaban:

57

Tampaknya powershell.exe tidak sepenuhnya mengevaluasi argumen skrip saat -Fileparameter digunakan. Secara khusus, $falseargumen diperlakukan sebagai nilai string, dengan cara yang mirip dengan contoh di bawah ini:

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

Alih-alih menggunakan -FileAnda bisa mencoba -Command, yang akan mengevaluasi panggilan sebagai skrip:

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

Seperti yang disarankan David , menggunakan argumen switch juga akan lebih idiomatis, menyederhanakan panggilan dengan menghilangkan kebutuhan untuk meneruskan nilai boolean secara eksplisit:

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True
Kaisar XLII
sumber
6
Bagi mereka (seperti saya) yang harus menyimpan parameter "-File", dan tidak dapat mengubah ke argumen switch, tetapi memiliki kendali atas nilai string yang dikirim, maka solusi paling sederhana adalah mengonversi parameter menjadi boolean menggunakan [System.Convert] :: ToBoolean ($ Unify); nilai string harus "Benar" atau "Salah".
Chris Haines
187

Penggunaan yang lebih jelas mungkin menggunakan parameter sakelar sebagai gantinya. Kemudian, hanya keberadaan parameter Unify yang berarti telah ditetapkan.

Seperti:

param (
  [int] $Turn,
  [switch] $Unify
)
David Mohundro
sumber
21
Ini harus menjadi jawaban yang diterima. Untuk diskusi lebih lanjut, Anda dapat mengatur nilai default seperti parameter lainnya seperti:[switch] $Unify = $false
Mario Tacke
Saya mengabaikan jawaban ini, karena saya yakin Boolean adalah cara yang tepat. Bukan itu. Switch merangkum fungsionalitas boolean, dan menghentikan jenis kesalahan ini: "Tidak dapat mengubah nilai" False "menjadi" System.Management.Automation.ParameterAttribute ". Switch berfungsi untuk saya.
TinyRacoon
2
@MarioTacke Jika Anda tidak menetapkan parameter sakelar saat menjalankan skrip maka secara otomatis disetel ke $false. Jadi tidak perlu menetapkan nilai default secara eksplisit.
doubleDown
Saran ini bekerja dengan sangat baik; dapat memperbarui salah satu params dari [bool] ke [switch] dan ini berhasil memungkinkan saya untuk meneruskan argumen melalui Penjadwal Tugas.
JustaDaKaje
12

Ini adalah pertanyaan yang lebih lama, tetapi sebenarnya ada jawaban untuk ini di dokumentasi PowerShell. Saya memiliki masalah yang sama, dan untuk sekali RTFM benar-benar menyelesaikannya. Hampir.

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

Dokumentasi untuk -File parameter menyatakan bahwa "Dalam kasus yang jarang terjadi, Anda mungkin perlu memberikan nilai Boolean untuk parameter switch. Untuk memberikan nilai Boolean untuk parameter switch dalam nilai parameter File, apit nama dan nilai parameter dalam tanda kurung kurawal, seperti berikut: -File. \ Get-Script.ps1 {-All: $ False} "

Saya harus menulisnya seperti ini:

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

Jadi tidak ada '$' sebelum pernyataan benar / salah, dan itu berhasil untuk saya, di PowerShell 4.0

LarsWA
sumber
1
Terima kasih sudah berbagi! Memecahkan masalah saya dengan sempurna.
Julia Schwarz
1
Tautan di jawaban tampaknya telah diubah isinya. Namun, saya menemukan jawabannya di sini
Slogmeister Extraordinaire
Tautan dokumentasi saat ini about_powershell.exe atau hanya berbunyi powershell -h.
Seth
Saya terkejut bahwa solusi canggung ini pernah berhasil - tidak ada di Windows PowerShell v5.1 (baik dengan atau tanpa pendahuluan $); perhatikan juga bahwa ini tidak lagi diperlukan di PowerShell Core . Saya telah meminta dokumentasi untuk dikoreksi; lihat github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0
11

Coba tetapkan jenis parameter Anda ke [bool]:

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

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

Contoh ini default $Unityuntuk $falsejika tidak ada masukan disediakan.

Pemakaian

.\RunScript.ps1 -Turn 1 -Unity $false
Filburt
sumber
1
Jawaban Kaisar XLII dan komentar Anda tentang -Fileparameter harus mencakup setiap aspek dari pertanyaan asli. Saya akan meninggalkan jawaban saya karena seseorang mungkin juga menemukan petunjuk saya tentang memberikan nilai default berguna.
Filburt
Filburt yang bagus. Jawaban Anda menyebabkan saya memeriksa skrip saya, yang sudah ditetapkan default sebagai nilai yang diperlukan $ false (saya menulisnya beberapa tahun yang lalu dan telah melupakan semuanya) - jadi saya bahkan tidak perlu menentukan parameter boolean bermasalah di baris perintah sekarang. Luar biasa :)
Zeek2
5

Saya pikir, cara terbaik untuk menggunakan / menetapkan nilai boolean sebagai parameter adalah dengan menggunakan skrip PS Anda seperti ini:

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

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

Jadi sekarang Anda bisa menggunakannya seperti ini:

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

Jadi dalam argumen dari cmd Anda dapat mengirimkan nilai boolean sebagai string sederhana :).

Drasius
sumber
2

Di PowerShell, parameter boolean dapat dideklarasikan dengan menyebutkan tipenya sebelum variabelnya.

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

Anda dapat menetapkan nilai dengan mengirimkan $ true | $ false

    GetWeb -includeTags $true
Ahmed Ali
sumber
Hanya meneruskan argumen input bernama secara eksplisit seperti itu akan berhasil. Terima kasih Ahmed
Steve Taylor
0

Untuk meringkas dan melengkapi jawaban yang ada , pada Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

Jawaban David Mohundro dengan tepat menunjukkan bahwa alih[bool][switch] - alih parameter Anda harus menggunakan parameter di PowerShell , di mana ada atau tidaknya nama sakelar ( -Unifyditentukan vs. tidak ditentukan) menyiratkan nilainya , yang membuat masalah aslinya hilang.


Namun, terkadang Anda mungkin masih perlu meneruskan nilai sakelar secara eksplisit , terutama jika Anda membuat baris perintah secara terprogram :


Di PowerShell Core , masalah asli (dijelaskan dalam jawaban Kaisar XLII ) telah diperbaiki .

Artinya, untuk meneruskan $truesecara eksplisit ke [switch]parameter bernama -UnifyAnda sekarang dapat menulis:

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

Nilai-nilai berikut dapat digunakan: $false, false, $true, true, tapi catatan yang lewat 0atau 1tidak tidak bekerja.

Perhatikan bagaimana nama sakelar dipisahkan dari nilai dengan :dan tidak boleh ada spasi kosong di antara keduanya.

Catatan: Jika Anda mendeklarasikan [bool]parameter alih-alih a [switch](yang biasanya tidak seharusnya), Anda harus menggunakan sintaks yang sama; meskipun -Unify $false seharusnya berfungsi, saat ini tidak - lihat masalah GitHub ini .


Di Windows PowerShell , masalah asli tetap ada , dan - mengingat bahwa Windows PowerShell tidak lagi dikembangkan secara aktif - tidak mungkin diperbaiki.

  • Solusi yang disarankan dalam jawaban LarsWA - meskipun didasarkan pada topik bantuan resmi saat tulisan ini dibuat - tidak berfungsi di v5.1

    • Masalah GitHub ini meminta dokumentasi dikoreksi dan juga menyediakan perintah pengujian yang menunjukkan ketidakefektifan solusi tersebut.
  • Menggunakan -Commandalih-alih -Fileadalah satu-satunya solusi efektif :

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

Dengan -CommandAnda secara efektif mengirimkan sepotong kode PowerShell , yang kemudian dievaluasi seperti biasa - dan di dalam PowerShell meneruskan $truedan $falseberfungsi (tetapi tidak true dan false, seperti sekarang juga diterima dengan -File).

Peringatan :

  • Penggunaan -Commanddapat menghasilkan interpretasi tambahan atas argumen Anda, seperti jika argumen berisi $karakter. (dengan -File, argumen adalah literal ).

  • Penggunaan -Commanddapat menghasilkan kode keluar yang berbeda .

Untuk detailnya, lihat jawaban ini dan jawaban ini .

mklement0
sumber
0

Saya memiliki sesuatu yang serupa ketika mengirimkan skrip ke fungsi dengan perintah-panggilan. Saya menjalankan perintah dalam tanda kutip tunggal, bukan tanda kutip ganda, karena ini kemudian menjadi string literal.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';

Bbb
sumber
0

Menjalankan skrip PowerShell di linux dari bash memberikan masalah yang sama. Menyelesaikannya hampir sama dengan jawaban LarsWA:

Kerja:

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

Tidak bekerja:

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
sumber
-3

Anda juga bisa menggunakan 0untuk Falseatau 1untuk True. Ini sebenarnya menunjukkan bahwa dalam pesan kesalahan:

Tidak dapat memproses transformasi argumen pada parameter 'Unify'. Tidak dapat mengkonversi nilai "System.String"jenis "System.Boolean", parameter jenis ini hanya menerima boolean atau angka, penggunaan $true, $false, 1 atau 0 sebagai gantinya.

Untuk info lebih lanjut, lihat artikel MSDN ini tentang Nilai dan Operator Boolean .

Rahs
sumber
10
Itu tidak berhasil. Itu mengharapkan bilangan bulat 1 atau 0, tetapi melewati itu -Filemenafsirkannya sebagai string, sehingga gagal dengan kesalahan yang sama.
Erti-Chris Eelmaa
Jawaban ini salah, karena saran tidak berhasil
mjs