36

通常,如果您想将 switch 参数的规范推迟到某个变量,您可以将表达式传递给 switch 参数,如 WhatIf 参数所示。

test.ps1

param ( [string] $source, [string] $dest, [switch] $test )
Copy-Item -Path $source -Destination $dest -WhatIf:$test

这使您在使用开关时具有极大的灵活性。但是,当您使用 cmd.exe 或其他方式调用 powershell 时,您会得到如下结果:

D:\test>powershell -file test.ps1 -source test.ps1 -dest test.copy.ps1 -test:$true

D:\test\test.ps1 : Cannot process argument transformation on
parameter 'test'. Cannot convert value "System.String" to type "System.Manageme
nt.Automation.SwitchParameter", parameters of this type only accept booleans or
 numbers, use $true, $false, 1 or 0 instead.
At line:0 char:1
+  <<<<
    + CategoryInfo          : InvalidData: (:) [test.ps1], ParentContainsError
   RecordException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,test.ps1

但是,通过-test:true和时会出现相同的结果-test:1。为什么这不起作用?Powershell 的类型转换系统不应该自动将这些字符串识别为可转换为 bool 或 switch 并转换它们吗?

这是否意味着当从其他系统(例如构建系统)调用 powershell 脚本时,有必要构建复杂的流控制结构来确定是否在命令字符串中包含一个开关,还是省略它?这似乎很乏味且容易出错,这让我相信事实并非如此。

4

2 回答 2

28

此行为已作为connect上的错误提交。这是一种解决方法:

powershell ./test.ps1 -source test.ps1 -dest test.copy.ps1 -test:$true
于 2012-07-08T18:21:50.260 回答
19

使用开关的 IsPresent 属性。例子:

function test-switch{
param([switch]$test)
  function inner{
    param([switch]$inner_test)
    write-host $inner_test
  }
  inner -inner_test:$test.IsPresent
}
test-switch -test:$true
test-switch -test
test-switch -test:$false

True
True
False

顺便说一句,我使用了函数而不是脚本,因此更容易测试。

于 2012-07-06T19:57:18.780 回答