问题
- 如何访问发送到 PowerShell 脚本(.ps1 文件)的参数?
- 您可以访问参数 A:按名称、B:按位置、C:两者的混合吗?
上下文
我最近尝试编写一个 PowerShell 脚本 (.ps1),该脚本将从 Windows 批处理文件 (.bat)(或可能的 cmd shell 或 AutoHotKey 脚本)调用 - 它将参数传递到 .ps1 脚本中使用(显示 toast 通知)。感谢 ss64.com 上的说明,我过去曾使用 $args
来做这种事情,但是由于某种原因我可以通过这种方式访问参数(尽管传递参数,$args[0] = ''
(空字符串)和 $args.Count = 0
),因此最终不得不删除所有 $args
代码,并将其替换为 Param( )
脚本代替。
我仍然不太清楚为什么,但我认为在尝试编写下一个脚本之前我应该弄清楚这一点......
代码示例 1:Args(未命名参数)
ToastNotificationArgs.ps1
-------------------------
Write-Debug "The script has been passed $($args.Count) parameters"
If (!$args[0]) { # Handle first parameter missing }
If (!$args[1]) { # Handle second parameter missing }
Import-Module -Name BurntToast
New-BurntToastNotification -Text "$args[0], $args[1]"
^ 我认为上面的代码是正确的,但就像我说的,由于某种原因我一直在努力访问参数并且无法弄清楚为什么。 (如果有人发现我做错了什么,请大声喊出来!)
$args[] 是一种有效的方法吗?鉴于它使用 ss64.com,我认为是这样。 ,但也许我需要注意一些陷阱/限制?
代码示例2:Param(命名参数)
ToastNotificationParams.ps1
---------------------------
Param(
[Parameter(Mandatory=$false, Position=0, ValueFromPipeline=$true)] [string]$Title,
[Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$true)] [string]$Message
)
Import-Module -Name BurntToast
New-BurntToastNotification -Text "$Title, $Message"
^ 这是让我的脚本最终运行的唯一方法。但是,当我传入参数时,我的调用 cmd 脚本按位置发送参数,即 (pwsh.exe -File "ToastNotificationParams.ps1""This is the title""Message gone Here"
) 而不是通过命名对。 (不确定这是否是最佳实践,但这就是我的脚本最初打算用来暂时保留它的方式)。
虽然这次 Param() 让我的脚本正常工作(并且我也意识到基于位置的参数的固有危险),但有时可能需要基于位置的方法(例如参数的数量未知)。 ..
代码示例 3:混合
ToastNotificationMix.ps1
------------------------
Param(
[Parameter(Mandatory=$false, Position=0, ValueFromPipeline=$true)] [string]$Title
)
Import-Module -Name BurntToast
For ( $i = 1; $i -lt $args.count; $i++ ) {
New-BurntToastNotification -Text "$Title, $args[i]"
}
这样的东西有效吗?..如果不是(或者有更好的解决方案),我们将不胜感激任何帮助!
提前致谢!
最佳答案
automatic
$args
variable仅适用于简单(非高级)函数/脚本。脚本自动变为advanced一种是使用[CmdletBinding()]
属性和/或每个参数至少一个[Parameter()]
属性。使用
$args
允许函数/脚本接受开放数量的位置参数,通常代替使用显式声明的参数,但也除了使用显式声明的参数之外。但它不允许传递命名参数(以预先声明的目标参数名称为前缀的参数,例如
-Title
)
为了稳健性,最好使用高级(类似 cmdlet)函数或脚本;这样的函数/脚本:
- 它们需要显式声明参数。
- 它们除了绑定(bind)到声明参数的参数之外不接受任何参数。
- 但是,您可以使用
[Parameter(ValueFromRemainingArguments)]
定义一个包罗万象的参数,该参数收集不绑定(bind)到任何其他预声明参数的所有位置参数。 。
- 但是,您可以使用
显式定义的参数默认情况下是位置参数,按照它们在
param(...)
中声明的顺序排列。阻止。- 您可以使用
[CmdletBinding(PositionalBinding=$false)]
关闭此默认设置。 , - 然后,您可以使用
Position
选择性启用位置绑定(bind)个人属性(property)[Parameter()]
属性。
- 您可以使用
当您通过 PowerShell 的 CLI 调用 PowerShell 脚本时的
-File
参数,调用语法基本上与从内部 PowerShell 调用脚本时相同;也就是说,您可以传递命名参数和/或 - 如果支持 - 位置参数。- 限制:
- 参数被视为文字。
- 不支持传递数组参数(
,
分隔的元素)。
- 如果您确实需要将参数解释为来自 PowerShell 内部的参数,请使用
-Command
/-c
相反 CLI 参数 - 参见this answer有关何时使用的指导
-File
与`-命令。
- 限制:
把它们放在一起:
ToastNotificationMix.ps1
:
[CmdletBinding(PositionalBinding=$false)]
Param(
[Parameter(Position=0)]
[string]$Title
,
[Parameter(Mandatory, ValueFromRemainingArguments)]
[string[]] $Rest
)
Import-Module -Name BurntToast
foreach ($restArg in $Rest) {
New-BurntToastNotification -Text "$Title, $restArg"
}
然后您可以从 cmd.exe
调用您的脚本例如,如下所示(我使用 pwsh.exe
,PowerShell(核心)CLI;对于 Windows PowerShell,使用 powershell.exe
):
仅位置绑定(bind):
:: "foo" binds to $Title, "bar" to $Rest
pwsh -File ./ToastNotificationMix.ps1 foo bar
命名绑定(bind)和位置绑定(bind)的混合:
:: "bar" and "baz" both bind to $Rest
pwsh -File ./ToastNotificationMix.ps1 -Title foo bar baz
关于PowerShell - 访问从 Windows cmd shell 发送的脚本参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67653712/