WMI win32_groupuser在PowerShell中性能降低

时间:2015-02-27 23:52:56

标签: powershell wmi

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

不是这种情况。这是我的剧本的主要内容:

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

如果该组存在,那么$ admin有一个正数,我可以报告。否则计数为0,这也没关系。

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

这个WMI组中的一个,我不知道,每次触摸时都会重建整个数据库,还是奇怪的?有关更快脚本的任何建议吗?

3 个答案:

答案 0 :(得分:1)

另一种方法是使用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。

答案 1 :(得分:0)

以这种方式尝试:

$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)
}

更多细节发表在我刚才写的博文中:

Weekend Scripter: Who are the Administrators?

答案 2 :(得分:0)

我终于走了另一条路:

$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的解决方案,所以非常感谢。