3

私は WMI を使用しており、ローカル コンピューターの OU を取得し、その OU 内のコンピューターの完全なリストを取得できるようにする PowerShell スクリプトを探しています。

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 オブジェクトを削除することが、パフォーマンスの類似性を維持する唯一の方法である可能性があります。

公正な警告: これは遅いです。本当に遅い。「あら、なんか壊しちゃったの!?」みたいな。スロー。私は OU を他の 20 台未満のコンピューターと共有しているコンピューターを対象としており、実行に 1 分近くかかります。1 台のコンピューターだけを最初に取得するだけでも 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;

Active Directory モジュールのロードを含め、2 秒かかります。すでに読み込まれている場合、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()私自身、このメソッドでオブジェクトを作成し、それらを破棄せず、シェルプロセスを一晩開いたままにしました。翌朝、すべてのメモリが消費されていたため、システムはほとんど応答しませんでした。モジュールはこれらのActiveDirectory問題を完全に回避し、さらにコードが軽いので、私がそのモジュールを好むよりも余分な数ミリ秒が本当に必要でない限り.

于 2014-12-09T16:48:29.043 に答える