如何根据脚本参数(即 msbuild,gradle)在 powershell 中执行任务

How to implement tasks in powershell based on a script parameter (i.e. msbuild, gradle)

是否可以在 PowerShell 中实现任务式系统,以便您可以执行以下操作:

.\script.ps1 build # runs build() function
.\script.ps1 publish # runs publish() function

我希望将 PowerShell 用于 building/publishing 应用程序而不是要求用户安装 gradle/msbuild 并且希望避免需要为每个添加的功能更新 switch 语句。

目前乱成这样:

#!/usr/bin/env powershell

param(
    $action = 'build'
)

function build() {
    echo 'build';
}

function publish() {
    echo 'publish';
}

switch($action) {
    'build' { build; }
    'publish' { publish; }
}

您可以使用 &call operator 来执行其 name(或者,在作为外部可执行文件的命令,路径) 存储在变量中。

然而,正如 marsze 指出的那样,盲目地按名称调用函数意味着您最终可能会调用一个 无关 的命令(任何形式)您的脚本,最好是无意的,最坏的情况是安全风险。

值得庆幸的是,PowerShell 提供了丰富的反射功能并公开了自己的解析 API,因此您可以确定脚本本身实际定义了哪些函数,并且只允许调用这些函数。

请注意,下面的代码还定义了一个list任务,它列出了脚本中定义的所有任务(函数)的名称。

#!/usr/bin/env powershell

param(
  [string] $task = 'build'
)

# -- Define a function for each task.
#    Note that functions must be defined *before* they are called in PowerShell.

function list {
  "Available tasks:"
  $functionNames
}

function build {
  'build'
}

function publish {
  'publish'
}

# -- Invoke the specified task by invoking the function of the same name.

# Get the list of the names of all functions defined in this script.
$functionNames = $MyInvocation.MyCommand.ScriptBlock.Ast.FindAll(
   { $args[0] -is [Management.Automation.Language.FunctionDefinitionAst] },
  $false
).Name

if ($task -in $functionNames) {

  # A known task - invoke it.
  & $task

}
else {

  # Report a script-terminating error, if the task name is uknown.
  throw "Unknown task: $task"
}