如何从批处理文件调用脚本时指定开关参数



我有一个脚本foo.ps1和一个批处理文件foo.cmd用于通过在文件资源管理器中双击cmd文件来启动脚本。

该脚本接受开关参数,但我不知道如何提供这种参数。简单的参数就可以了。

Foo.ps1:

param(
[Parameter()]
[Switch]$MySwitch,
[Parameter()]
[string]$Name
)
Write-Host "`$MySwitch : $MySwitch, `$Name : $name"

Foo.cmd:

Powershell -noprofile -NonInteractive -file "%~dp0foo.ps1" -Name "abc"    

如果我只用"名称"调用脚本,它可以工作。但是如果我指定 MySwitch,它会停止工作:

Foo2.cmd:

Powershell -noprofile -NonInteractive -File "%~dp0foo.ps1" -Name "abc" -MySwitch:$false

错误是:

C:tempfoo.ps1 : Impossible de traiter la transformation d'argument sur le paramètre «MySwitch». Impossible de convertir la valeur «System.String» en type « System.Management.Automation.SwitchParameter». Les paramètres booléens acceptent seulement des valeurs booléennes et des nombres, tels que $True, $False, 1 ou 0.
+ CategoryInfo          : InvalidData : (:) [foo.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,foo.ps1

在Windows PowerShell中,当使用powershell.exe的s
-File参数时,无法传递布尔值 - 这已经在PowerShell
(Core)7+中得到了纠正,其CLI为pwsh.exe[1]。

使用 JosefZ 建议的解决方法

使用-Command(-c)而不是-File会使PowerShell将参数视为PowerShell源代码而不是文字参数,在这种情况下,$false被正确识别(为简洁起见,省略其他CLI参数)。

powershell -c "& "%~dp0foo.ps1" -Name 'abc' -MySwitch:$false"  

注意:

  • &调用运算符必须用于调用脚本文件,因为它的路径是用引号括起来的

  • PowerShell期望命令行上嵌入的"字符作为"进行转义(而不是`""",就像它在PowerShell的工作方式一样)。

    使用-Command,如果需要在嵌入的
    • "..."字符串中嵌入逐字",请使用`"(原文如此)。
    • 虽然您可以将脚本路径括在'...'中,但为了避免转义的需要,如果扩展的目录文件路径 (%dp0) 恰好包含'字符本身,则此类调用将中断。
  • 有关何时使用-File-Command和适用的不同语法规则,请参阅此答案。


关于概念说明

  • 你的代码已使用首选方式在 PowerShell 中传递布尔参数:[switch]参数(有时称为标志)。

  • 开关
  • 参数暗示布尔值:如果指定了给定的开关 - 仅按名称 - (-MySwitch),则隐含$true;如果完全不存在,则隐含$false。也就是说,简单地省略-MySwitch:$false也可以解决您的问题

    • 相比之下,应避免使用[bool]类型参数(总是需要参数)。这篇文章将[bool][switch]参数进行了对比。
  • 虽然(PowerShell-内部)您(总是)可以传递显式(如您尝试使用
    -MySwitch:$false,请注意所需的:分隔符空格不起作用) -仅在以下情况下需要这样做:

    • 如果要通过以编程方式确定值的变量传递布尔值。

    • 在极少数情况下,开关默认为$true,您需要覆盖它。

      • 出于概念原因,最好避免在用户代码中将交换机参数默认为$true:如有必要,否定交换机的逻辑;例如Write-Host-NoNewLine交换机。

      • 但是,PowerShell 的一些常见参数是开关参数,实际上可以通过其首选项变量对应项默认为$true

        • 一个值得注意的例子是常见的-Confirm开关参数:相应的$ConfirmPreference首选项变量的值使得有必要传递-Confirm:$false才能选择退出确认提示,即使使用$ConfirmPreference的默认值(High)。

[1] PowerShell (Core) 7+ 在使用-File时支持以下布尔值:$true$falsetruefalse(以及$null,但其解释不同:脚本(包括-File)和函数将其解释为$false,而 cmdlet 将其解释为$true(!))。
请注意,对于-Command- 因此在所有PowerShell代码中 -truefalse不起作用,但01起作用.
不幸的是,如果传递不受支持的值,则在所有方案中都会收到相同的错误消息,这在-File方案中误导性地表明01也可以工作。

最新更新