Powershell:针对不同环境的两个参数定义?

Powershell: Two parameter definitions for different environments?

我有一个又长又大的 PS5 powershell 脚本,它有几个参数,定义在脚本文件开头的 param() 部分。 这些参数是字符串和哈希表,包括主机名、IP 地址、域等。

此脚本 运行 在我的环境中完全没问题,但现在它在所有参数都不同的第二个环境中也应该 运行。

因此,在不更改所有脚本命令的情况下,我想定义具有不同值的第二个参数部分,并在脚本顶部提供一个“开关”变量,例如:

param1(
... my params1 ...)

param2(
... my params2 ... )

string configToUse = "param1"

我偶然发现了 powershell 参数集,但我想这不是我要找的。 我过去也使用过一些节点定义文件 (.psd1),但我想将所有内容保存在一个文件中,只需双击即可执行,而无需在命令行上传递 -param1 或 -param2。

有人能给我指出正确的方向吗?

谢谢!

param 语句只是为了能够像您提到的那样将参数传递给脚本,使用 -param "value" 语法,我 强烈推荐 以这种方式将参数传递给脚本,而不是将静态值放入脚本中!它更简洁、更健壮、更透明、更易于维护、更便携且更易于记录。

如果您仍然需要 double-click 功能,可能为了方便起见,您可以制作一个 批处理文件 来调用您的脚本。它只是一行(@ 阻止该行被打印到控制台):

@powershell -File "your-script.ps1" -Param1 "value 1"

然后您可以为每个环境创建单独的批处理文件。

call-mysript-env-1.bat
call-mysript-env-2.bat

或者,您可以使用 快捷方式 以相同的方式调用带有参数的脚本来完成相同的操作。

如果,仅当出于某种原因,您真的不想这样做时,您可以 完全省略 param 语句(您无论如何都不使用它的功能)。毕竟,参数基本上只是常规变量。你可以这样做:

### start of parameters ###
$configToUse = "param1"

switch ($configToUse) {
   "param1" {
       $MyParam = "value 1"
   }
   "param2" {
       $MyParam = "value 2"
   }
}
#### end of parameters ###
# rest of your script ....

好的设计实践通常强调让函数(包括脚本)只接受来自参数的数据。这样做可能有助于故障排除和维护。但是为参数分配默认值并不直接违反该准则。这实际上取决于您的听众 and/or 您的用例。此外,您想有条件地分配默认 and/or 条件参数值是多么疯狂。

虽然您的代码无疑更复杂,但下面是一个示例,说明如何有条件地为参数分配默认值。

Function Test-ConditionalParameterValues
{
    Param(
        [Parameter( Mandatory = $false )]
        [String]$Environment = 
                {
                    If( $Host.Name -eq 'Visual Studio Code Host' ) { 'VSCode'  }
                    If( $Host.Name -eq 'ConsoleHost' ) { 'ConsoleHost'  }
                }.Invoke()
        ) # End Parameter Block...

Write-Host $Environment

} # End Function Test-ConditionalParameterValues

我必须警告这可能会在视觉上变得混乱并且有点不正统。团队环境中的可读性和可维护性可能是一个问题。

注意:根据您分配的内容,您可能不需要脚本块语法。当赋值可能是另一个 cmdlet 或函数的输出时,如果确实需要,您通常可以使用 (...) 换行。

此外,在参数设计建议中有时会忽略可测试性。我有很多实现 -Environment 参数的函数。环境参数通常有一个验证集属性,如 [ValidateSet( 'Prod','Dev' )。类似于 的一部分,有内部代码根据参数分配不同的值。我的一个常见用例是定义 SQL 连接字符串。这使我可以测试任意内部更改,而不会冒生产损坏等风险...

这可能看起来像:

Function Insert-SomeData
{
Param(
    [Parameter(Mandatory = $false)]
    [ValidateSet( 'Prod', 'Dev' )]
    [String]$Environment = 'Prod'
    ) # End Parameter Block...

Switch ($Environment)
{
    'Prod' { $ConnString = "Production Connection String" }
    'Dev'  { $ConnString = "Dev Connection String"        }
}

# Rest of code would follow

这种方法使您可以方便地在多个环境中使用简写参数进行调用,而且还可以在需要时灵活地 运行 使用手动指定的数据,尽管您可能需要删除或更改 [ValidateSet()] 以达到所需的灵活性。

注意:在正常使用中,当 运行 在不同的环境中时,调用仍然会略有不同,但您不必在调用本身中敲定大型数据集,如哈希表等。

我必须重申,您的 audience/consumers 对于您如何做这样的事情很重要。如果我计划将脚本发布到画廊,即使在 运行 时间选择硬编码连接字符串也不会很好地工作,但是像上面这样的方法在企业环境中对于特殊任务和自动化代码非常有效。