3

我正在使用 WMI 并试图找到一个 powershell 脚本,该脚本将允许我获取本地计算机的 OU,然后获取该 OU 中计算机的完整列表。

4

1 回答 1

6

干得好:

$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 中找到计算机,但我不确定如何在不进行大量查询的情况下将其限制为单个 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 毫秒。

如果您无权访问ActiveDirectoryPowerShell 模块,则可以使用[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 系统,或者如果调用但结果从未使用过,则ADSI 系统已知包含内存泄漏。FindAll()我自己用这种方法创建了对象,然后没有处理它们,并让我的 shell 进程在一夜之间打开,当我第二天早上进来时,我的系统几乎没有响应,因为所有的内存都被消耗掉了。该ActiveDirectory模块完全避免了这些问题,并且代码更轻,所以除非你真的需要那些额外的几毫秒,否则我会喜欢那个模块。

于 2014-12-09T16:48:29.043 回答