WMI win32_groupuser PowerShell 中的性能下降

WMI win32_groupuser slow performance in PowerShell

不确定这是不是我。我编写了一个脚本来检查远程服务器上本地管理员中是否存在域组。由于我公司有 20 多个域——其中许多域彼此隔离——我不确定这是否适用于使用 AD cmdlet。相反,我想我应该直接查询每台服务器的 WMI,这是一种通常对我有用的解决方案。

在这种情况下不是。这是我的脚本的主要部分:

$admin = Get-WmiObject win32_groupuser –computername $server | Where-Object $_.PartComponent -match $domaingroup} | Measure-Object

如果该组存在,则 $admin 的计数为正数,我可以就此进行报告。否则计数为 0,这也没关系。

但是今天,我被要求检查 200 台服务器上是否存在该组,但我的脚本失败了。这是狗慢。从每台服务器获取结果需要五到十 分钟。我可以更快地登录到服务器并直观地检查组。

这是 WMI 组之一吗,我不知道,每次触摸它时都会重建整个数据库,还是奇怪的东西?对更快的脚本有什么建议吗?

另一种方法是使用 ADSI 查询,例如:

$Results = ForEach($Server in (Get-Content .\ServerList.txt)){
    $group = [ADSI]"WinNT://$Server/Administrators"
    [PSCustomObject]@{'Server'=$Server
    'Group Found' = [boolean](@($group.Invoke("Members")) |
        foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}|
        Where{ $_ -match $domaingroup}| Measure-Object)
    }
}

如果在本地管理员组中找到 AD 组,那应该会留下一组服务器名称和 True/False。

这样试试:

$computerName = "."
$wmiEnumOpts = new-object System.Management.EnumerationOptions
$wmiEnumOpts.BlockSize = 20
$argList = @{
  "Class" = "Win32_Group"
  "ComputerName" = $computerName
  "Filter" = "LocalAccount=TRUE AND SID='S-1-5-32-544'"
}
get-wmiobject @argList | foreach-object {
  $_.GetRelated("Win32_Account","Win32_GroupUser","","",
  "PartComponent","GroupComponent",$FALSE,$wmiEnumOpts)
}

更多细节在博客中post我刚才写过:

Weekend Scripter: Who are the Administrators?

我终于走了一条不同的路:

$group = [ADSI]"WinNT://$Server/$LocalGroupName"
$members = @($group.Invoke("Members"))
foreach ($member in $members) {
$MemberName = $member.GetType().Invokemember("Name","GetProperty",$null,$member,$null)
if ($MemberName -eq $DomainGroupName) {
$GroupFound++ }}

因此,如果 $GroupFound 最终大于 0,则报告查找成功。否则,将其重置为 0 并在我列表中的下一台服务器上重新开始。每台服务器会在不到 10 秒左右的时间内报告,大约有 25:1 改进。

非常接近 TheMadTechnician 的解决方案,非常感谢。