简体   繁体   中英

How do I use WMI to get the current OU of a computer and list all other computers in that OU?

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

Here you go:

$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'";

I think this also finds computers in child OUs, but I'm not sure how to limit it to a single OU without doing a ton of queries. The query syntax is just rather sparse. Eliminating the child OU objects after retrieval of the full list might be the only way to do it with any semblance of performance.

Fair warning: This is slow. Really slow. Like "Oh, crap did I break something?!" slow. I pointed it at a computer that shares an OU with less than 20 other computers, and it takes nearly a minute to run. Even the first fetching of just the single computer takes more than 1 second.

Here's what I would recommend:

$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;

That takes 2 seconds, including loading the Active Directory module. With it already loaded, that takes less than 200 milliseconds.

If you don't have access to the ActiveDirectory PowerShell module, then you can use an [ADSISearcher] . These are also a pain to use because of how results are presented, but they're even faster than the ActiveDirectory module, which is basically just a wrapper for this.

$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();

This runs in about 50 milliseconds.

However, beware that the ADSI system is known to contain memory leaks if it's not called correctly or if FindAll() is called and the results are never used. I myself have created objects with this method and then not disposed of them and left my shell process open overnight, and when I came in the next morning my system was all but unresponsive because all the memory had been consumed. The ActiveDirectory module avoids these problems entirely, and is even more code light, so unless you really need those extra few milliseconds than I would favor that module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM