【问题标题】:Trouble executing powershell script on multiple remote machines在多台远程机器上执行 powershell 脚本时遇到问题
【发布时间】:2015-05-01 20:03:20
【问题描述】:

我需要生成我们网络上属于其工作站本地管理员组成员的所有用户的列表。我在这里找到了一个脚本https://gallery.technet.microsoft.com/scriptcenter/List-local-group-members-762b48c5#content,它通过Powershell 执行WMI 查询来列出本地组成员。我已经测试了这个脚本,它运行良好,但我一直在尝试修改它以获取要检查的计算机列表,这就是我遇到麻烦的地方。这是我所做的:

function LocalAdmins
{
  param([string]$GroupName = "Administrators")

    begin
    {
        # Get all workstations listed in this text file
        $WorkStations = Get-Content -Path C:\useful_lists\testLocal.txt

        # Initialize an array to hold the results of the query
        $arr = @()

    # hash table for storing computer name, member pairings
    $hash = @();
    }

    process
    {
        foreach ($machine in $WorkStations)
        {
            $wmi = Get-WmiObject -ComputerName $machine -Query `
                "SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$machine',Name='$GroupName'`""

            # Parse out the username from each result and append it to the array
            if ($wmi -ne $null)
            {
                foreach($item in $wmi)
                {
                    $arr += ($item.PartComponent.Substring($item.PartComponent.IndexOf(',') + 1).Replace('Name=', '').Replace("`"", ''))
                }
            }

            # Return a hash table comprised of two columns: Computer Name & Members
            $hash += @{ComputerName=$machine;Members=$arr}
        }
    }

    end
    {
        return $hash
    }
}

当我运行未修改的脚本时,这是我得到的输出:

PS > (Get-LocalGroupMembers -ComputerName "<COMPUTER NAME>" -GroupName "Administrators").Members

ACCOUNTNAME
ACCOUNTNAME
ACCOUNTNAME

PS >

但是,当我运行我修改的这个脚本的版本时,我得到了这个:

PS > (LocalAdmins -GroupName "Administrators").Members
PS >

我相当确定问题在于我如何设置第一个 foreach 循环来运行 wmi 查询,或者该查询的结果如何存储在哈希表中。我不确定我能做些什么来解决这个问题。

提前感谢任何可以提供帮助的人!

更新

根据 mortenya 的建议,我编辑了我的测试文本文件,使其仅包含一台计算机。这样做,连同取出 foreach ($machine in $computers) 循环按预期工作,产生以下结果:

>> LocalAdmins -GroupName "Administrators"

Name               Value
----               ----
ComputerName       {computerName.domain}
Members            {account, account, account, account}

>>

但是,当使用上面的代码合并多台机器时,回过头来尝试让它工作(我从最初的帖子开始更新它),我得到以下信息:

>> LocalAdmins -GroupName "Administrators"

Name               Value
----               -----
ComputerName       computerName1.domain
Members            {}
ComputerName       computerName2.domain
Members            {}

>>

为什么使用列表中的一台计算机可以获得管理员组的成员,但向列表中添加第二台计算机会导致我无法在任何一台计算机上检索该组的成员?

【问题讨论】:

  • 这个LocalAdmins -GroupName "Administrators" 能得到什么?我也没有看到你初始化$hash。你可能只需要像$hash = @() 这样的行
  • 我知道您从脚本中心获得了该脚本,但我不明白为什么它会创建一个 $Workstations 变量只是为了将其推入一个数组。我会只运行 WMI 查询,确保它返回你想要的。
  • 嗨,马特,感谢您的意见。我编辑了帖子以显示我刚输入 LocalAdmins -GroupName "Administrators" 时得到的结果。我还在 Begin{} 块中初始化了 $hash 数组,但是,这并没有解决问题。

标签: powershell remote-access wmi-query


【解决方案1】:

因此,如果您要使用 Begin{}、Process{} 和 End{},请将它们用于它们的用途,在 Begin{} 块中初始化所有数组和常量变量。

Begin {
    # Get all workstations listed in this text file
    $WorkStations = Get-Content -Path C:\useful_lists\testLocal.txt

    # Store the contents of that list in an array
    $computers = @()

    $hash = @()
}

除此之外,几个月前我也做过同样的事情,它有点乱,但它会吐出一个计算机列表以及谁在本地管理员组中。部分是为了练习一些不同的方法。

$output = 'c:\psresults\ListOfLocalAdministratorsGroup.txt'
$results = New-Object System.Collections.ArrayList

$objSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")
$objgroup = $objSID.Translate( [System.Security.Principal.NTAccount])
$objgroupname = ($objgroup.Value).Split("\")[1]

foreach($server in (Get-ADComputer -Filter *).name)
{
    $admins = New-Object System.Collections.ArrayList
    $group =[ADSI]"WinNT://$server/$objgroupname" 
    $members = @($group.psbase.Invoke("Members"))
    $members | foreach {
        $obj = new-object psobject -Property @{
            Server = $Server
            Admin = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
    }    
    #$obj
        $admins.Add($obj)
    } 
    $results.Add($admins)
}
$results | Out-File $Output

我在某处找到了它的精髓,然后对其进行了一些修改。

编辑:我只是将它放入 ISE,它似乎工作正常

$machine = "testsrv"
$groupname = "Administrators"

$wmi = Get-WmiObject -ComputerName $machine -Query `
"SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$machine',Name='$GroupName'`""

if ($wmi -ne $null) 
{ 
    foreach ($item in $wmi) 
    { 
        $arr += ($item.PartComponent.Substring($item.PartComponent.IndexOf(',') + 1).Replace('Name=', '').Replace("`"", '')) 
    } 
} 

$hash = @{ComputerName=$machine;Members=$arr} 
return $hash

让它在一台机器上运行,然后开始尝试重新添加循环。

编辑 2.0:

  1. 我制作了一个 .txt 文件,其中只有计算机名称,而不是 FQDN,这对我来说很好用。只需稍加修改,我就可以使用您的脚本运行它并获得结果。

  2. 尽管我说过 Begin{} 块,$arr 变量需要在 foreach ($machine in $WorkStations) 循环内初始化。这样做的原因是,当循环运行时,它会创建 $arr 数组,添加我们想要的数据,将该数据插入到全局变量中,然后清理 $arr 变量。如果我们将此设为全局,则在函数完成之前不会对其进行清理,我们将继续添加它,这不是我们在这种情况下真正想要的。

  3. 让多台机器工作时遇到的问题可能是您构建结果表的方式。

【讨论】:

  • 嗨 mortenya,感谢您发布此回复。我更新了我的帖子,以反映我根据您的建议所做的一些更改。在一台机器上测试脚本运行良好,但是,将新机器添加到列表中仍然存在问题。您是否在我更新的脚本中看到任何仍然可能导致问题的内容?谢谢。
  • @wrigley06 我已经在本地工作了。我意识到你需要在 foreach 循环中初始化 $arr 数组才能正常工作,我将编辑我的答案来解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 2022-10-12
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多