如何在PowerShell中处理命令行参数

Aar*_*ann 464 powershell command-line-arguments

处理命令行参数的"最佳"方法是什么?

似乎对"最佳"方式有几个答案,因此我坚持如何处理如下简单的事情:

script.ps1 /n name /d domain
Run Code Online (Sandbox Code Playgroud)

script.ps1 /d domain /n name.
Run Code Online (Sandbox Code Playgroud)

有没有一个可以更好地处理这个问题的插件?我知道我在这里重新发明轮子.

显然我已经不是很漂亮而且肯定不是"最好的",但它确实有效..而且它是UGLY.

for ( $i = 0; $i -lt $args.count; $i++ ) {
    if ($args[ $i ] -eq "/n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "/d"){ $strDomain=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-d"){ $strDomain=$args[ $i+1 ]}
}
Write-Host $strName
Write-Host $strDomain
Run Code Online (Sandbox Code Playgroud)

nai*_*sts 863

你正在重新发明轮子.普通PowerShell脚本具有参数开始-,如script.ps1 -server http://devserver

然后param在文件开头的部分处理它们.

您还可以为参数指定默认值,如果不可用则从控制台读取它们或停止脚本执行:

 param (
    [string]$server = "http://defaultserver",
    [Parameter(Mandatory=$true)][string]$username,
    [string]$password = $( Read-Host "Input password, please" )
 )
Run Code Online (Sandbox Code Playgroud)

你可以简单地在脚本里面

write-output $server
Run Code Online (Sandbox Code Playgroud)

因为所有参数都成为脚本范围中可用的变量.

在此示例中,$server如果在没有脚本的情况下调用脚本,则获取默认值,如果省略-username参数则脚本将停止,并且如果省略则请求终端输入-password.

更新:您可能还希望将"flag"(布尔值true/false参数)传递给PowerShell脚本.例如,您的脚本可能会接受"强制",其中脚本在不使用强制时以更仔细的方式运行.

该关键字是[switch]参数类型:

 param (
    [string]$server = "http://defaultserver",
    [string]$password = $( Read-Host "Input password, please" ),
    [switch]$force = $false
 )
Run Code Online (Sandbox Code Playgroud)

在脚本内部,您可以像这样使用它:

if ($force) {
  //deletes a file or does something "bad"
}
Run Code Online (Sandbox Code Playgroud)

现在,在调用脚本时,您需要设置switch/flag参数,如下所示:

.\yourscript.ps1 -server "http://otherserver" -force
Run Code Online (Sandbox Code Playgroud)

如果您明确要声明未设置该标志,则会有一种特殊语法

.\yourscript.ps1 -server "http://otherserver" -force:$false
Run Code Online (Sandbox Code Playgroud)

指向相关Microsoft文档的链接(适用于PowerShell 5.0;链接中也提供了版本3.0和4.0):

  • 事实上,PowerShell的一大优势是它提供了一个易于使用的标准参数解析基础设施. (53认同)
  • @naivists,来自PowerShell 2.0而不是`[string] $ username = $(throw"-username is required.")`有强制参数的语法:`[Parameter(Mandatory = $ true)] [string] $ username` .以下是有关这些技术之间差异的更多信息:http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/22/use-powershell-to-make-mandatory-parameters.aspx (13认同)
  • 当没有提供arg时要小心这个bug; powershell将从命令行中获取任何额外的文本:.\ yourscript.ps1 -server"http:// serv"-password"mypass"typo这将神奇地将"拼写错误"分配给$ username. (7认同)
  • 使用param块似乎还有其他意想不到的后果:http://stackoverflow.com/questions/40940819/import-pssession-fails-in-script-works-in-shell (4认同)
  • @sheamus:这不是错误!Powershell 将按照给定的顺序处理和分配参数,除非使用正确的参数名称覆盖,例如,如果您的参数块列出:$user $pass $server,并且您执行 yourscript.ps1 abc,a 将是设置为 $user,b 设置为 $pass,c 设置为 $server,除非你特别指定它们!所以,如果你说:yourscript.ps1 -pass abc,$pass 将被设置为a,剩下的(未命名的)参数将用于填充缺失的,按照参数块中列出的顺序,所以$user = b, $server = c。 (3认同)
  • 处理用户名和密码的更好方法是使用“Credential”类型,它将在输入期间隐藏密码并将其存储为“SecureString”。(我并不完全相信“SecureString”的价值,但至少它降低了它被意外打印在输出中的风险。) (2认同)
  • @sheamus 避免“拼写错误”情况的一种方法是显式拒绝位置绑定,这可以针对每个参数或全局完成。只需将 [CmdletBinding(PositionalBinding=$false)] 添加到 cmdlet 的顶部即可。 (2认同)