简体   繁体   English

连字符/破折号参数对PowerShell意味着什么?

[英]What does hyphen/dash parameter mean to PowerShell?

I've found out that, if I pass only a dash to an argument of PowerShell 5.1 script on Windows 10, like this: 我发现,如果仅在Windows 10上将破折号传递给PowerShell 5.1脚本的参数,例如:

powershell.exe -File Test.ps1 -

I get a strange error message saying: 我收到一条奇怪的错误消息:

C:\\path\\Test.ps1 : Cannot process argument because the value of argument "name" is not valid. C:\\ path \\ Test.ps1:无法处理参数,因为参数“名称”的值无效。 Change the value of the "name" argument and run the operation again. 更改“名称”参数的值,然后再次运行该操作。

  • CategoryInfo : InvalidArgument: (:) [Test.ps1], PSArgumentException CategoryInfo:InvalidArgument:(:) [Test.ps1],PSArgumentException
  • FullyQualifiedErrorId : Argument,Test.ps1 FullyQualifiedErrorId:Argument,Test.ps1

The Test.ps1 is only: Test.ps1仅是:

echo "foo"

The actual problem I face though is that, when the script declares any mandatory parameter: 我遇到的实际问题是,当脚本声明任何强制性参数时:

param (
    [Parameter(Mandatory)]
    $value
)

echo "foo"

Then executing the script the same way (with - argument) does nothing at all. 然后以相同的方式(使用-参数)执行脚本完全没有执行任何操作。 No output. 无输出。 No error message. 没有错误讯息。 It just hangs for a few seconds. 它只是挂了几秒钟。 And then a control returns to a command prompt. 然后控件返回到命令提示符。

C:\path>powershell.exe -File Test.ps1 -

C:\path>_

What does the - mean to PowerShell (5.1)? -对PowerShell(5.1)意味着什么?


On the contrary, with PowerShell 2.0 on Windows 7, I get script usage in this case: 相反,在Windows 7上使用PowerShell 2.0,在这种情况下,我可以使用脚本:

C:\path>powershell.exe -File Test.ps1 -
Test.ps1 [-value] <Object> [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]


C:\path>_

What makes sense (a missing mandatory parameter). 有什么意义(缺少必需的参数)。

And without the mandatory parameter declaration, the script works (prints it output): 在没有强制性参数声明的情况下,脚本可以工作(将其打印输出):

C:\path>powershell.exe -File Test.ps1 -
foo

C:\path>_

This isn't an answer but I'm curious as well. 这不是答案,但我也很好奇。 If you've already figured it out I'd be interested in what you found. 如果您已经知道了,我会对您发现的内容感兴趣。 Otherwise, in case it helps, Powershell -h says everything after -file is the script and any arguments passed to it. 否则,如果有帮助, Powershell -h-file之后的所有内容都是脚本以及传递给它的所有参数。

-File
    Runs the specified script in the local scope ("dot-sourced"), so that the
    functions and variables that the script creates are available in the
    current session. Enter the script file path and any parameters.
    File must be the last parameter in the command, because all characters
    typed after the File parameter name are interpreted
    as the script file path followed by the script parameters.

Tokenizer reads it in as a CommandArgument. 令牌生成器将其作为CommandArgument读入。

Powershell >> $Errors = $Null    
Powershell >> [System.Management.Automation.PSParser]::Tokenize("powershell -file test.ps1 -", [ref]$Errors)[3]

Content     : -
Type        : CommandArgument
Start       : 26
Length      : 1
StartLine   : 1
StartColumn : 27
EndLine     : 1
EndColumn   : 28

So it seems like the issue is further up the chain but I couldn't find a simple way to call the Parser functions to test. 因此,问题似乎更进一步,但我找不到一种简单的方法来调用Parser函数进行测试。

I do see that there's a case that shouldn't occur where the error is swallowed and null returned which might cause it to just stop like it does in your example 我确实看到有一种情况不应该发生 ,即错误被吞没并返回null,这可能导致它像您的示例一样停止运行

The behavior should be considered a bug - something that starts with - but isn't a valid parameter name should be passed as a positional argument rather than reporting an error. 该行为应被认为是一个错误 -开头为-但不是有效的参数名称,应将其作为位置参数传递,而不是报告错误。

The bug affects: 该错误影响:

  • Windows PowerShell (as of v5.1.18362.145) - it is unclear if a fix will ever be made. Windows PowerShell(从v5.1.18362.145起)-尚不清楚是否会进行修复。

    • As you state, whether you (a) get the error message ( ... the value of argument "name" is not valid ... ) or (b) the - is quietly ignored depends on whether your parameter has a parameter attribute such as [Parameter(Mandatory)] [1] and/or your param() block has a [CmdletBinding()] attribute (if so, (b) applies). 如您陈述的那样,您(a)是否收到错误消息... the value of argument "name" is not valid ... )或(b) -是否被静默忽略取决于您的参数是否具有参数属性,例如作为[Parameter(Mandatory)] [1]和/或您的param()块具有[CmdletBinding()]属性(如果是,则(b)适用)。
  • PowerShell Core 6.x - that is, the problem will be fixed in v7 (current as of this writing: v7.0.0-preview.3); PowerShell Core 6.x-即,该问题将在v7中解决 (撰写本文时为最新版本:v7.0.0-preview.3); I don't know if 6.2.2, the stable version current as of this writing, will be fixed - we'll see what happens to the bug report on GitHub you've filed. 我不知道6.2.2(即撰写本文时的最新稳定版本)是否将得到修复-我们将您提交的GitHub上查看错误报告的情况。


As for a workaround (works analogously in PowerShell Core): 至于解决方法 (在PowerShell Core中类似地工作):

Use -Command instead of -File . 使用-Command而不是-File

While that changes the semantics of how the command line is parsed [2] , in simple cases such as this one the difference won't matter: 尽管这改变了命令行解析的语义[2] ,但在这种简单情况下,区别并不重要:

C:\> powershell -Command ./Test.ps1 -  # note the "./"

Note the ./ , because using -Command ( -c ) makes PowerShell parse the arguments as if they were PowerShell code, and the usual restrictions re executing scripts by filename only apply (to prevent accidental execution of a file in the current directory, you need a path component to explicitly signal that intent, hence prefix ./ or .\\ is needed). 请注意./ ,因为使用-Command-c )使PowerShell像解析PowerShell代码一样对参数进行解析,并且按文件名重新执行脚本的通常限制仅适用-Command (为防止意外执行当前目录中的文件,您可以需要一个路径组件来明确表示该意图,因此需要前缀./.\\ )。

If your script file path needed quoting, you'd have to use quoting and prepend & , the call operator; 如果您的脚本文件路径需要用引号引起来,则必须使用引号并在&前面加上呼叫操作符; eg: 例如:

C:\> powershell -Command "& \"./Test.ps1\" -"

[1] Adding a [Parameter()] attribute to a declared parameter implicitly makes the enclosing script/function an advanced one, in which case different parsing rules apply. [1]在声明的参数上添加[Parameter()]属性会隐式使封闭的脚本/函数成为高级脚本/函数,在这种情况下,将应用不同的解析规则。 The [CmdletBinding[] attribute, which is applied to a param(...) block as a whole, explicitly marks a script / function as an advanced one. [CmdletBinding[]上应用到param(...)块的[CmdletBinding[]属性将脚本/函数显式标记为高级。

[2] See this answer for the differences between how -File and -Command arguments are parsed. [2]见这个答案对于如何之间的差异-File-Command参数解析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM