【问题标题】:How to pass a variable (array of strings) to other PowerShell scripts如何将变量(字符串数组)传递给其他 PowerShell 脚本
【发布时间】:2014-05-09 22:30:18
【问题描述】:

我在一个包含字符串数组的 PowerShell 脚本中有一个变量 $Tasks,我需要将该变量传递给其他 PowerShell 脚本并对其执行操作,例如循环遍历数组并对每个执行操作项目(字符串)。

但是,在我的变量从数组转换为字符串的过程中的某个时刻(通常在它遇到 script2.ps1 时),我无法循环遍历它。我需要做什么才能在整个过程中将变量保持为数组?

这是变量的工作流程:

Script1.ps1

$Tasks = @(
"Task1 - Name1",
"Task2 - Name2",
"Task3 - Name3"
)

powershell "& {. $pwd\Script2.ps1 -BuildNum $BuildNum; Run-Validation -Tasks $Tasks}"

Script2.ps1

param(
    $Tasks=$()
)

Function Run-Validation
{
    param($Tasks)

    If ($Tasks)
    {
        Test-Tasks $Tasks
    }
}

Script3.ps1

Function Test-Tasks ($Tasks)
{
    ForEach ($Task in $Tasks)
    {
        do_stuff
    }
}

【问题讨论】:

    标签: arrays powershell


    【解决方案1】:

    发生这种情况的原因是您在双引号字符串中扩展了数组$Tasks。在你的命令行被传递给 PowerShell.exe 之前,它被扩展为:

    Arg 0 is <& {. C:\Script2.ps1 -BuildNum ; Run-Validation -Tasks Task1 - Name1 Task2 - Name2 Task3 - Name3}>
    

    所以Run-Validation -Tasks 参数只能看到“Task1”。如果您要查看 Run-Validation 函数中的 $args,您会看到其余的参数。

    顺便说一句,为什么要调用另一个 Powershell.exe 会话?为什么不直接调用:

    . $PSScriptRoot\Script2.ps1 -BuildNum $BuildNum
    Run-Validation -Tasks $Tasks
    

    请注意,上述方法仅适用于如果您消除了 Script2.ps1 中的脚本级别 $Tasks 参数。如果没有,当您点 source Script2.ps1 以访问 Run-Validation 函数时,Script2.ps1 中的 $Tasks 会有效地覆盖 Script1.ps1 中设置的值。

    如果你真的想在单独的 PowerShell 会话中调用它,你可以这样做:

    $OFS="','"
    powershell "& {. $pwd\Script2.ps1 -BuildNum $BuildNum; Run-Validation -Tasks '$Tasks'}"
    

    【讨论】:

    • 嗨 Keith,如果我省略了 param 块,那么根本不会传入任何值。使用 param 块,$Tasks 的值作为字符串传递。
    • 那么为什么在调用 script2.ps1 时不使用 -Tasks 参数呢?您也确实使用了未在脚本块中声明的 -BuildNum 参数。
    • 我上面的例子是我实际脚本的一个非常精简的版本。 -BuildNum 实际上在我的脚本中的 Script2.ps1 的 param 块中声明为一个字符串: [string]$BuildNum=$() 除了我传入的许多其他参数(它们都是字符串)。如果我实际上在 Script1.ps1 中将变量 $Tasks 创建为单个字符串(例如 $Tasks = 'Task1 - Name1'),那么一切正常。事实上,我所有的变量都是字符串,因为它们包含单个事物的值。使用 $Tasks,我有不止一件事情要处理,这就是为什么我想把 then 放入一个数组中。
    • 嗨,Keith,抱歉,不知道您的问题是什么意思:“为什么在调用 script2.ps1 时不使用 -Tasks 参数?”
    • C:\Script2.ps1 -BuildNum $BuildNum - 你运行 Script2.ps1 并为 BuildNum 参数传入一个参数,但你没有为 Tasks 参数传入一个值。
    【解决方案2】:

    我发现将我的 PowerShell 脚本构建为函数很有帮助。与其通过多个脚本一直传递 $Tasks,我建议您在准备好使用它们时拉入 $Tasks。

    这将等同于您的 Script1.ps1

    taskList.ps1

    Function Get-Tasks()
    {
        $Tasks = @(
            "Task1 - Name1",
            "Task2 - Name2",
            "Task3 - Name3"
        )
        return $Tasks
    }
    

    这相当于您的 Script2.ps1Script3.ps1 的组合:

    # Dot source the scripts we will need
    .$PSScriptRoot\taskList.ps1
    
    # Get the list of tasks
    $taskList = Get-Tasks
    
    if ($taskList -ne $null)
    {
        foreach ($task in $taskList)
        {
            # Do stuff here
            "Processing task: " + $task
        }
    }
    

    注意: $PSScriptRoot 将从当前工作目录加载。如果此文件位于其他位置,请使用完整路径。

    但是,如果您仍想保留当前的结构,您可以简单地将 Script.1 更新为以下内容

    # Dot source the scripts we will need
    .$PSScriptRoot\Script3.ps1
    
    $Tasks = @(
        "Task1 - Name1",
        "Task2 - Name2",
        "Task3 - Name3"
    )
    
    Run-Validation -Tasks $Tasks
    

    【讨论】:

    • 嗨 Beard,我上面的示例是我实际脚本的一个非常简化的版本。 Script1.ps1 实际上是一个安装/部署脚本,它包含多个变量(每个变量通常包含一个字符串的值)、函数调用和用于在服务器上安装/部署事物的一般工作流任务。安装完成后,我从 Script1.ps1 调用验证脚本来验证刚刚安装的内容。这是 Script2.sp1。它包含一个参数列表、函数调用,并用作验证的工作流,它调用 Script3.ps1,其中包含我的所有函数。
    • 还有第四个报告脚本。另外,Script2.ps1、Script3.ps1 和 Script4.ps1 过去都在一个脚本中,但随着时间的推移,单体脚本变得太大且难以维护,这就是为什么我决定按功能目的将它们分解(工作流程、功能、报告)。无论如何,如果我给我的变量 $Tasks 一个字符串的单个值(例如“任务名称”),那么一切都很好。事实上,我传入的所有变量都包含一个字符串的值。这是我第一次尝试将变量作为数组传递,但到目前为止还没有工作。
    【解决方案3】:

    我在脚本中使用了这样的参数定义:

    [cmdletbinding()]
    Param(
        [Parameter(Position=0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [ValidateNotNullorEmpty()]
        [Alias("cn", "name")]
        [String[]]$var
    )
    

    在本例中,您可以将:[String]$var定义为单个字符串变量,或将[String[]]$var定义为字符串变量数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多