【问题标题】:How do I use WMI to get the current OU of a computer and list all other computers in that OU?如何使用 WMI 获取计算机的当前 OU 并列出该 OU 中的所有其他计算机?
【发布时间】:2015-02-07 11:50:23
【问题描述】:

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

【问题讨论】:

  • 为什么是 WMI? \root\directory\LDAP 真是让人头疼。使用ActiveDirectory 模块甚至System.DirectoryServices.DirectorySearcher 会更加容易。

标签: powershell active-directory wmi ou


【解决方案1】:

给你:

$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 毫秒。

如果您无权访问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 system is known to contain memory leaks 如果没有被正确调用或者如果 FindAll() 被调用并且结果永远不会被使用。我自己已经用这种方法创建了对象,然后没有处理它们,而是让我的 shell 进程在一夜之间打开,当我第二天早上进来时,我的系统几乎没有响应,因为所有的内存都被消耗掉了。 ActiveDirectory 模块完全避免了这些问题,而且代码更简洁,所以除非你真的需要额外的几毫秒,否则我会喜欢那个模块。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    相关资源
    最近更新 更多