我发现,如果仅在Windows 10上将破折号传递给PowerShell 5.1脚本的参数,例如:
powershell.exe -File Test.ps1 -
Run Code Online (Sandbox Code Playgroud)
我收到一条奇怪的错误消息:
C:\ path \ Test.ps1:无法处理参数,因为参数“名称”的值无效。更改“名称”参数的值,然后再次运行该操作。
- CategoryInfo:InvalidArgument:(:) [Test.ps1],PSArgumentException
- FullyQualifiedErrorId:Argument,Test.ps1
该Test.ps1只:
echo "foo"
Run Code Online (Sandbox Code Playgroud)
我遇到的实际问题是,当脚本声明任何强制性参数时:
param (
[Parameter(Mandatory)]
$value
)
echo "foo"
Run Code Online (Sandbox Code Playgroud)
然后以相同的方式(带有-参数)执行脚本完全没有任何作用。无输出。没有错误讯息。它只是挂了几秒钟。然后控件返回到命令提示符。
echo "foo"
Run Code Online (Sandbox Code Playgroud)
-对PowerShell(5.1)意味着什么?
相反,在Windows 7上使用PowerShell 2.0,在这种情况下,我可以使用脚本:
param (
[Parameter(Mandatory)]
$value
)
echo "foo"
Run Code Online (Sandbox Code Playgroud)
有什么意义(缺少必需的参数)。
在没有强制性参数声明的情况下,脚本可以工作(将其打印输出):
C:\path>powershell.exe -File Test.ps1 -
C:\path>_
Run Code Online (Sandbox Code Playgroud)
该行为应被视为错误- 开头-但不是有效参数名称的内容应作为位置参数传递,而不是报告错误。
该错误影响:
Windows PowerShell(自 v5.1.18362.145 起)- 目前尚不清楚是否会进行修复。
... the value of argument "name" is not valid ...)或(b)-被悄悄忽略取决于您的参数是否具有参数属性,例如 [Parameter(Mandatory)][1]和/或您的param()块具有[CmdletBinding()]属性(如果是这样,( b) 适用)。PowerShell Core 6.x - 也就是说,该问题将在 v7 中得到解决(截至撰写本文时当前版本:v7.0.0-preview.3);我不知道 6.2.2(截至撰写本文时的稳定版本)是否会得到修复 - 我们将看看您在 GitHub 上提交的错误报告会发生什么情况。
至于解决方法(在 PowerShell Core 中类似):
使用-Command而不是-File.
虽然这改变了命令行解析方式的语义[2],但在像这样的简单情况下,差异并不重要:
C:\> powershell -Command ./Test.ps1 - # note the "./"
Run Code Online (Sandbox Code Playgroud)
请注意./,因为使用-Command( -c) 会使 PowerShell 解析参数,就像它们是 PowerShell 代码一样,并且仅适用按文件名重新执行脚本的常见限制(为了防止意外执行当前目录中的文件,您需要一个路径组件来显式表示该意图,因此需要前缀./or )。.\
如果您的脚本文件路径需要引用,则必须使用 quoting 和 prepend &(调用运算符);例如:
C:\> powershell -Command "& \"./Test.ps1\" -"
Run Code Online (Sandbox Code Playgroud)
[1][Parameter()]向声明的参数添加属性隐式地使封闭的脚本/函数成为高级脚本/函数,在这种情况下,应用不同的解析规则。该[CmdletBinding[]属性应用于param(...)整个块,明确地将脚本/函数标记为高级脚本/函数。
[2]有关解析方式和参数之间的差异,请参阅此答案。-File-Command