问题描述
我正在使用WMI,并试图找到一个Powershell脚本,该脚本将允许我获取本地计算机的OU,然后获取该OU中计算机的完整列表.
I'm using WMI and am trying to find a powershell script that will allow me get the OU of the local computer and then get a full list of computers in that OU.
推荐答案
在这里:
$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对象可能是唯一实现类似效果的方法.
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.
警告:这很慢.真的慢.就像哦,可怜我弄碎了什么?!"慢的.我将其指向与少于20台其他计算机共享一个OU的计算机,并且运行将近一分钟.即使是仅单台计算机的第一次读取也要花费超过1秒钟的时间.
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.
这是我推荐的:
$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毫秒的时间.
That takes 2 seconds, including loading the Active Directory module. With it already loaded, that takes less than 200 milliseconds.
如果您无权访问 ActiveDirectory
PowerShell模块,则可以使用 [ADSISearcher]
.由于结果的显示方式,使用它们也很麻烦,但它们甚至比 ActiveDirectory
模块更快,该模块基本上只是对此的包装.
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();
这大约需要50毫秒.
但是,请注意,已知 ADSI系统包含内存泄漏如果未正确调用它,或者是否调用了 FindAll()
并且从不使用结果.我本人已经用这种方法创建了对象,然后不处理它们,并使我的shell进程一夜之间打开,第二天早上我来时,我的系统几乎没有响应,因为所有内存都被消耗掉了. ActiveDirectory
模块完全避免了这些问题,并且代码更加轻巧,因此除非您真的需要比我偏爱的模块少几个毫秒.
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.
这篇关于如何使用WMI获取计算机的当前OU并列出该OU中的所有其他计算机?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!