如何使用WMI获取计算机当前的OU并列出该OU中的所有其他计算机?

3

我正在使用WMI,并尝试查找一个允许我获取本地计算机OU并获得该OU中所有计算机完整列表的PowerShell脚本。


6
为何选择WMI?\root\directory\LDAP实在太麻烦了。使用ActiveDirectory模块或者System.DirectoryServices.DirectorySearcher甚至更加容易。 - Bacon Bits
1个回答

8
这是你要的:
$ComputerName = '<Name of Computer>';
$Computer = Get-WmiObject -Namespace 'root\directory\ldap' -Query "Select DS_distinguishedName from DS_computer where DS_cn = '$ComputerName'";
$OU = $Computer.DS_distinguishedName.Substring($Computer.DS_distinguishedName.IndexOf('OU='));
$ComputersInOU = Get-WmiObject -Namespace 'root\directory\ldap' -Query "Select DS_cn, DS_distinguishedName from DS_computer where DS_distinguishedName like '%$OU'";

我认为这也会在子组织单位中找到计算机,但我不确定如何将其限制为单个组织单位而不进行大量查询。查询语法相当简洁。在检索完整列表后消除子OU对象可能是以任何性能形式完成的唯一方法。

公平警告:这很慢。非常慢。就像“哦,该死我把东西弄坏了吗?”的速度那样。我让它指向一个与不到20台其他计算机共享OU的计算机,需要近一分钟才能运行。即使仅获取单个计算机的第一次提取也需要超过1秒钟。

以下是我的建议:

$ComputerName = '<Name of Computer>';
Import-Module -Name ActiveDirectory -Cmdlet Get-ADComputer, Get-ADOrganizationalUnit;
$Computer = Get-ADComputer $ComputerName;
$OU = $Computer.DistinguishedName.SubString($Computer.DistinguishedName.IndexOf('OU='));
$ComputersInOU = Get-ADComputer -Filter * -SearchScope OneLevel -SearchBase (Get-ADOrganizationalUnit $OU).DistinguishedName;

那需要2秒钟,包括加载Active Directory模块。如果已经加载,则只需要不到200毫秒。
如果您无法访问ActiveDirectory PowerShell模块,则可以使用[ADSISearcher]。由于结果的呈现方式,它们也很难使用,但比ActiveDirectory模块更快,后者基本上只是这个的包装器。
$ComputerName = '<Name of Computer>';
$ADSISearcher = New-Object System.DirectoryServices.DirectorySearcher;
$ADSISearcher.Filter = '(&(name=' + $ComputerName + ')(objectClass=computer))';
$ADSISearcher.SearchScope = 'Subtree';
$Computer = $ADSISearcher.FindAll();

$OU = $($Computer.Properties.Item('distinguishedName')).Substring($($Computer.Properties.Item('distinguishedName')).IndexOf('OU='));
$OUADsPath = 'LDAP://' + $OU;

$ADSISearcher = New-Object System.DirectoryServices.DirectorySearcher;
$ADSISearcher.Filter = '(objectClass=computer)';
$ADSISearcher.SearchScope = 'OneLevel';
$ADSISearcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry($OUADsPath);
$ComputersInOU = $ADSISearcher.FindAll();

这个程序运行大约需要50毫秒。
然而,要注意如果ADSI系统未正确调用或者调用了FindAll()但结果从未使用,则可能存在内存泄漏。我曾经使用这种方法创建对象,但没有处理它们并将我的Shell进程保持开启状态过夜。第二天早上我发现我的系统几乎无法响应,因为所有内存都已被消耗。 ActiveDirectory模块完全避免了这些问题,并且代码更加简洁。因此,除非您真的需要那几毫秒的额外时间,否则我会推荐使用该模块。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接