【问题标题】:Powershell calling a function if script has mandatory parameters如果脚本具有强制参数,则 Powershell 调用函数
【发布时间】:2017-11-24 16:35:05
【问题描述】:

我对 PowerShell 还很陌生,但我很喜欢它,因为它可以在我们的 Windows 机器上自动执行大量任务。我喜欢你可以从其他脚本调用函数,但是我编写的脚本都使用用户可以提供的参数(因此同事更容易使用它们)。

在我的脚本中,有一个参数通常是必需的。我面临的问题是使用强制参数从脚本调用函数。

这是一个简单的例子:

Param(

 [Parameter()]
 [ValidateNotNullOrEmpty()]
 [string]$VirtualMachine=$(throw "Machine name missing!"),

 [int]$Attempts = 150

 )

Function DoSomething($VirtualMachine, $Attempts){

    write("$VirtualMachine and $Attempts")

 }

将此作为脚本运行,您将提供-VirtualMachine "VMnameHere" -Attempts 123。运行它会产生VMnameHere and 123。完美的!但是..如果我尝试将其作为另一个脚本中的函数调用..

这里的例子:

. ".\Manage-Machine.ps1"

DoSomething -VirtualMachine "nwb-thisisamachine" -Attempts 500

这产生了一个错误:

Machine name missing!
At C:\Users\something\Desktop\Dump\play\Manage-Machine.ps1:33 char:28
+  [string]$VirtualMachine=$(throw "Machine name missing!"),
+                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Machine name missing!:String) [], RuntimeException
    + FullyQualifiedErrorId : Machine name missing!

这显然是因为该字段是强制性的。在这种情况下,我调用函数的方式有问题吗?如果它所属的脚本具有强制参数,是否有另一种方法来调用该函数,因为如果我删除参数的验证,它就可以工作。

希望有一些意见,

谢谢!

【问题讨论】:

  • ps1文件有没有调用函数的行?因为您的样本不应生成输出。如果确实如此,那么只需调用 ps1 并提供您的参数
  • 我会使用 [parameter(Mandatory = $true)] 并删除 =$(throw "Machine name missing!")
  • @Matt 不,目前,如果我调用该函数(如在没有强制参数的情况下描述的那样)它运行得很好。运行脚本会很好,但我真正想要的是在一个脚本中拥有多个函数,然后在另一个脚本中需要它时调用每个函数,而不是运行整个脚本。它将运行最后调用的任何函数,我一次无法使用函数。
  • 詹姆斯所说的仍然会引发错误。不需要手动处理没有输入的情况是他的建议。 Throw 虽然可以提供更好的信息
  • @JakubS 您说过“用户可以提供的参数”,但如果它是 CI 流程的一部分,则使用 -NonInteractive 标志运行 powershell,任何缺少的强制参数都会导致错误和将返回非零退出代码。

标签: windows powershell parameters powershell-4.0


【解决方案1】:

我会使用[parameter(Mandatory = $true)] 并删除=$(throw "Machine name missing!")

然后您可以使用-NonInteractive 标志 (documentation link) 运行 powershell,任何缺少的强制参数都将导致错误,并且将返回非零退出代码。

这个返回码应该被你的 CI 进程获取,它自己会处理错误。

【讨论】:

  • 您的建议与 OP 的问题无关。您的建议只会改变一件事:在 interactive 调用场景中,[Parameter(Mandatory)] 会在没有强制参数值的情况下 prompt 而不是抛出异常(通过 $(throw "Machine name missing!")) .
  • 这是一篇旧帖子,但 -NonInteractive 标志解决了我的问题。
【解决方案2】:

我不确定这样做是不是个好主意,但听起来以下方法可行:

Param(

  [ValidateNotNullOrEmpty()]
  # Do NOT use = $(Throw ...) or [Parameter(Mandatory)].
  [string]$VirtualMachine, 

  [int]$Attempts = 150

)

# Determine if the script is being "dot-sourced".
# Note: The `$MyInvocation.Line -eq ''` part detects being run from the
#       ISE or Visual Studio Code, which implicitly perform sourcing too.
$isDotSourced = $MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq ''

# NOT sourced? Enforce mandatory parameters.
if (-not $isDotSourced) {
  if (-not $VirtualMachine) { Throw "Machine name missing!" }
}

Function DoSomething($VirtualMachine, $Attempts) {
  "$VirtualMachine and $Attempts"
}


# NOT sourced? Call the default function or
# do whatever you want the script to do when invoked as a whole.
if (-not $isDotSourced) {
  DoSomething $VirtualMachine $Attempts
}
  • . .\Manage-Machine.ps1 将仅定义函数(在本例中为DoSomething),以供稍后调用;
    由于没有任何脚本参数在技术上被声明为强制,因此不带参数的调用将成功(与您的尝试不同,throw 语句总是启动 - 无论是直接调用还是点源)。

  • 相比之下,.\Manage-Machine.ps1 将强制存在$VirtualMachine 参数值并立即调用DoSomething,传递参数值。

请注意,当然,您的函数也可以从输入参数和添加验证属性中受益。

【讨论】:

    猜你喜欢
    • 2011-08-12
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 2016-02-09
    相关资源
    最近更新 更多