Powershell:在param语句中将多行txt文件值作为数组传递

时间:2013-07-11 20:26:04

标签: powershell

我有一个包含服务器列表的文本文件,每行一个,如:

SERVER1
SERVER2
SERVER3

当我对文件执行Get-Content时,我确实看到输出为:

SERVER1
SERVER2
SERVER3

所以现在我正在编写一个函数,我希望将多个服务器作为一个数组,并迭代函数中的数组。该功能目前是这样的:

function Get-LocalAdministrators 
{
    param(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [string[]]$computers
    )

    foreach ($computername in $computers)
    {
        $ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}

        foreach ($ADMIN in $ADMINS) 
        {
            $admin = $admin.replace("\\$computername\root\cimv2:Win32_UserAccount.Domain=","") # trims the results for a user
            $admin = $admin.replace("\\$computername\root\cimv2:Win32_Group.Domain=","") # trims the results for a group
            $admin = $admin.replace('",Name="',"\")
            $admin = $admin.REPLACE("""","") # strips the last "

            $objOutput = New-Object PSObject -Property @{
                Machinename = $($computername)
                Fullname = ($admin)
                #DomainName  =$admin.split("\")[0]
                #UserName = $admin.split("\")[1]
            }

        $objReport+=@($objOutput)
        }

        return $objReport
    }
}

然后我计划将该函数称为:

Get-Content “C:\temp\computers.txt” | Get-LocalAdministrators

然而,当我运行该函数时,我可以看到$ computers的值是{SERVER3}(即只是文件中的最后一行。)我试图通过Google找到答案,虽然有很多数组引用/示例,但我找不到将文件中的值与param语句中的数组相结合的结果。请原谅我的PS新手无知,并提供我需要的线索......谢谢。

更新:链接到PowerGUI脚本编辑器中运行的脚本的屏幕截图,显示运行期间$ computers的值:debug run screenshot

1 个答案:

答案 0 :(得分:1)

当您通过管道将对象传递给函数时,一次只有一个传递给您的函数 - 而不是整个数组。所以你不需要foreach循环,也不需要在函数中使$computers成为一个数组。

此外,当您拥有管道功能时,您应该使用beginprocessend关键字。每个表示一个脚本块 - begin是一个执行的脚本块(当管道“设置”时),process是要为每个对象执行的脚本块通过管道传递,end就像begin一样,只有在最后一个项目通过后才会运行。

最低限度,你的功能应该是这样的:

function Get-LocalAdministrators
{
    param(
    [Parameter(Mandatory=$True,Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
    [string]$computer
    )
process{
$ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}
# Do other stuff here
}
}

The MSDN documentation说(这是get-help about_functions - 还有更多内容):

  

将对象管道化为功能
        任何函数都可以从管道获取输入。你可以控制一下         函数使用Begin,Process和End从流水线输入流程         关键字。以下示例语法显示了三个关键字:

      function <name> { 
          begin {<statement list>}
          process {<statement list>}
          end {<statement list>}
      }

  The Begin statement list runs one time only, at the beginning of 
  the function.  

  The Process statement list runs one time for each object in the pipeline.
  While the Process block is running, each pipeline object is assigned to 
  the $_ automatic variable, one pipeline object at a time. 

  After the function receives all the objects in the pipeline, the End 
  statement list runs one time. If no Begin, Process, or End keywords are 
  used, all the statements are treated like an End statement list.

编辑:看到OP添加的完整代码后,这就有效了。请注意,我已经对上面描述的代码进行了更改。

function Get-LocalAdministrators 
{
    param(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [string]$computer
    )

    process{
        $ADMINS = get-wmiobject -computername $computer -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computer',Name='administrators'""" | % {$_.partcomponent}

        foreach ($ADMIN in $ADMINS) 
        {
            $admin = $admin.replace("\\$computername\root\cimv2:Win32_UserAccount.Domain=","") # trims the results for a user
            $admin = $admin.replace("\\$computername\root\cimv2:Win32_Group.Domain=","") # trims the results for a group
            $admin = $admin.replace('",Name="',"\")
            $admin = $admin.REPLACE("""","") # strips the last "

            $objOutput = New-Object PSObject -Property @{
                Machinename = $($computer)
                Fullname = ($admin)
                #DomainName  =$admin.split("\")[0]
                #UserName = $admin.split("\")[1]
            }

        $objReport+=@($objOutput)
        }

        $objReport
    }
}