Bir komut isteminden bir PowerShell betiğine boole değerleri nasıl iletilir


104

Bir toplu iş dosyasından bir PowerShell betiği çağırmam gerekiyor. Betiğin argümanlarından biri boole değeridir:

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

Komut aşağıdaki hatayla başarısız olur:

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

Şu an itibariyle, komut dosyamın içinde boole dönüşümüne bir dize kullanıyorum. Ancak Boole bağımsız değişkenlerini PowerShell'e nasıl iletebilirim?

Yanıtlar:


58

Powershell.exe'nin -Fileparametre kullanıldığında komut dosyası bağımsız değişkenlerini tam olarak değerlendirmediği anlaşılıyor . Özellikle $falsebağımsız değişken, aşağıdaki örneğe benzer şekilde bir dize değeri olarak ele alınmaktadır:

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

Kullanmak yerine , aramayı komut dosyası olarak değerlendirecek olan -Filedeneyebilirsiniz -Command:

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

As David anlaşılacağı, bir anahtar argümanı kullanarak da açıkça bir boolean değer geçmek ihtiyacı ortadan kaldırarak çağrıyı basitleştirilmesi, daha deyimsel olacaktır:

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

6
"-File" parametresini tutması gereken ve bir anahtar argümanına geçemeyen, ancak gönderilen dize değerleri üzerinde kontrole sahip olanlar için en basit çözüm, parametreyi bir [System.Convert] kullanan boolean :: ToBoolean ($ Unify); dize değerleri bu durumda "True" veya "False" olmalıdır.
Chris Haines

187

Bunun yerine anahtar parametreleri kullanmak daha net bir kullanım olabilir. Daha sonra, yalnızca Unify parametresinin varlığı ayarlandığı anlamına gelir.

Şöyle:

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

21
Kabul edilen cevap bu olmalıdır. Tartışmayı daha da ileri götürmek için, diğer parametreler gibi varsayılan bir değer ayarlayabilirsiniz:[switch] $Unify = $false
Mario Tacke

Bu cevabı göz ardı ettim çünkü Boolean'ın gidilecek yol olduğundan emindim. O değil. Anahtar, boole işlevini kapsüller ve şu tür hataları durdurur: "" False "değeri" System.Management.Automation.ParameterAttribute "türüne dönüştürülemiyor. Anahtarlar benim için çalıştı.
TinyRacoon

2
@MarioTacke Betiği çağırırken switch parametresini belirtmezseniz, otomatik olarak olarak ayarlanır $false. Bu nedenle, açık bir şekilde varsayılan bir değer ayarlamaya gerek yoktur.
doubleDown

Bu öneri çok işe yaradı; parametrelerden birini [bool] 'dan [switch]' e güncelleyebildi ve bu, argümanı Görev Zamanlayıcı aracılığıyla başarıyla geçirmeme izin verdi.
JustaDaKaje

12

Bu daha eski bir sorudur, ancak aslında PowerShell belgelerinde buna bir yanıt vardır. Ben de aynı sorunu yaşadım ve bir kez olsun RTFM gerçekten çözdü. Neredeyse.

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

-File parametresine ilişkin dokümantasyon, "Nadir durumlarda, bir switch parametresi için bir Boolean değeri sağlamanız gerekebilir. File parametresinin değerinde bir switch parametresi için bir Boolean değeri sağlamak için, parametre adını ve değerini içine alın küme ayraçları, örneğin aşağıdakiler: -File. \ Get-Script.ps1 {-All: $ False} "

Bunu şöyle yazmalıydım:

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

Yani doğru / yanlış ifadesinden önce '$' yok ve bu benim için PowerShell 4.0'da çalıştı


1
Paylaşım için teşekkürler! Sorunumu mükemmel bir şekilde çözdüm.
Julia Schwarz

1
Yanıttaki bağlantının içeriği değişmiş görünüyor. Ancak cevabı burada
Slogmeister Extraordinaire

About_powershell.exe hakkındaki mevcut dokümantasyon bağlantısı alternatif olarak sadece çaldı powershell -h.
Seth

Bu garip çözümün şimdiye kadar işe yaramasına şaşırdım - Windows PowerShell v5.1'de olmadı (ne liderli ne de lidersiz $); ayrıca PowerShell Core'da artık gerekli olmadığını unutmayın . Belgelerin düzeltilmesini istedim; bkz. github.com/MicrosoftDocs/PowerShell-Docs/issues/4964
mklement0

11

Parametrenizin türünü şu şekilde ayarlamayı deneyin [bool]:

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

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

Bu örnek, varsayılan $Unityiçin $falseherhangi bir giriş temin edilir ise.

Kullanım

.\RunScript.ps1 -Turn 1 -Unity $false

1
İmparator XLII'nin cevabı ve -Fileparametre ile ilgili yorumunuz orijinal sorunun her yönünü kapsamalıdır. Cevabımı bırakacağım çünkü birisi varsayılan bir değer sağlama konusundaki ipucumu yararlı bulabilir.
Filburt

Aferin Filburt. Cevabınız, zaten varsayılan olarak gerekli değer $ false olarak belirlenmiş olan betiğimi kontrol etmeme neden oldu (bunu birkaç yıl önce yazdım ve her şeyi unutmuştum) - bu yüzden sorunlu boole parametresini şimdi komut satırı. Mükemmel :)
Zeek2

5

Bence, boole değerini parametre olarak kullanmanın / ayarlamanın en iyi yolu, PS betiğinizde şu şekilde kullanmaktır:

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

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

Yani şimdi bunu şu şekilde kullanabilirsiniz:

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

Yani cmd'deki argümanlarda boole değerini basit dizge olarak geçirebilirsiniz :).


2

PowerShell'de boolean parametreleri, değişkenlerinden önce türlerinden bahsedilerek bildirilebilir.

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

$ True | $ false

    GetWeb -includeTags $true

Sadece adlandırılmış girdi argümanlarını açıkça bu şekilde iletmek bir tedavi işe yaradı. Teşekkürler Ahmed
Steve Taylor

0

To özetlemek ve tamamlayıcı mevcut cevapları Windows PowerShell v5.1 / PowerShell Çekirdek 7.0.0-preview.4 itibariyle:

David Mohundro cevabı haklı olduğunu işaret yerine [bool]parametreleri kullanmanız gerektiğini [switch]parametreleri PowerShell , varlığı vs yokluğu anahtarı adının ( -UnifyBelirtilen vs değil belirtilen) değerini ima orijinal problem ortadan kalkmış yapar.


Bununla birlikte, bazen , özellikle programlı olarak bir komut satırı oluşturuyorsanız, anahtar değerini açık bir şekilde geçirmeniz gerekebilir :


In PowerShell Çekirdek , orijinal sorun (anlatıldığı İmparator XLII cevabı ) olmuştur sabit .

Yani, adlı $truebir [switch]parametreye açıkça geçmek-Unify şimdi yazabilirsiniz:

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

Aşağıdaki değerler kullanılabilir: $false, false, $true, truegeçen değil not olduğunu 0veya 1does not işi.

Anahtar adının değerden nasıl ayrıldığına :ve boşluk olmaması gerektiğine dikkat edin ve ikisi arasında .

Not: a [bool]yerine bir parametre bildirirseniz [switch](genellikle yapmamalısınız), aynı sözdizimini kullanmanız gerekir; olsa -Unify $false gerekir çalışmak, şu anda değil - bkz bu GitHub sorunu .


In Windows PowerShell , özgün problem devam Windows PowerShell artık aktif gelişmiş olduğu göz önüne alındığında - - ve sabit almak mümkün değildir.

  • Önerilen geçici çözüm LarsWA cevabı dayandığı halde - resmi yardım konusuna bu yazı olarak - does not v5.1 iş

    • Bu GitHub sorunu , belgelerin düzeltilmesini ister ve ayrıca geçici çözümün etkisizliğini gösteren bir test komutu sağlar.
  • -CommandBunun yerine kullanmak -File, tek etkili çözümdür :

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

Bununla birlikte , daha sonra her zamanki gibi değerlendirilen bir PowerShell kodunu-Command etkili bir şekilde geçiriyorsunuz - ve PowerShell içinde geçiyor ve çalışıyor (ancak değil ve şimdi de kabul edildiği gibi ).$true$false truefalse-File

Uyarılar :

  • Kullanmak -Command, $karakter içeriyor gibi argümanlarınızın ek yorumlanmasına neden olabilir . (ile -File, bağımsız değişkenler değişmezdir ).

  • Kullanmak farklı bir çıkış koduna-Command neden olabilir .

Ayrıntılar için bu yanıta ve bu yanıta bakın .


0

İnvoke-command ile bir işleve bir komut dosyası iletirken benzer bir şey yaşadım. Komutu çift tırnak yerine tek tırnak içinde çalıştırdım, çünkü daha sonra değişmez bir dize olur.'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';


0

Bash'den linux üzerinde powershell betiklerini çalıştırmak da aynı sorunu veriyor. Hemen hemen LarsWA'nın cevabıyla aynı şekilde çözüldü:

Çalışma:

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

Çalışmıyor:

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

Ayrıca 0for Falseveya 1for kullanabilirsiniz True. Aslında hata mesajında ​​şunu öneriyor:

'Unify' parametresinde bağımsız değişken dönüşümü işlenemez. Değeri dönüştürülemez "System.String"tipine "System.Boolean", bu tip parametreler sadece Boolean veya numaraları, kullanımını kabul $true, $false, 1 veya 0 yerine.

Daha fazla bilgi için Boole Değerleri ve Operatörleri hakkındaki bu MSDN makalesine bakın .


10
Bu çalışmıyor. 1 veya 0 tam sayı bekler, ancak onu geçmek onu -Filedize olarak yorumlar, dolayısıyla aynı hatayla başarısız olur.
Erti-Chris Eelmaa

Öneri işe yaramadığı için bu cevap yanlış
mjs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.