Hey, Scripting Guy!Active Directory を参照する

Microsoft Scripting Guys

コードのダウンロード: HeyScriptingGuy2009_02.exe(151 KB)

目次

ヘルプを提供する
核心
ヘルパ関数

ご存じかもしれませんが、編集者と私は最近新しく常勤の Microsoft Scripting Guys になったばかりで、scripter@microsoft.com 電子メール アカウントに届く何千通もの電子メールをより分けることに多くの時間を費やすこのごろです。実際に調査を依頼したわけではありませんが、たぶん、電子メールで届いている質問の中で最も多いのは、「Active Directory ブラウザはどこで入手できますか」というものです。ですが、私たちはそんなものを見たことがありません。よく調べたのですが、見つけることはできませんでした。

結局、インターネット掲示板に秘密のメッセージをいくつか投稿し、暗号で返事をもらいました。これを解読したところ、ADSI Scriptomatic が実のところ Active Directory ブラウザであるという内容でした。これは Active Directory ブラウザという名前ではなく、また、実際、このツールの目的は Active Directory の参照ではないので (これは ADSI スクリプトの作成を支援するツールです)、私は、Active Directory スキーマを参照できる Windows PowerShell スクリプトを記述することに決めました。奇妙なことに、このスクリプトの名前は BrowseActiveDirectorySchema.ps1 です。このスクリプトを図 1 に示します。

図 1 BrowseActiveDirectorySchema.ps1

Param($action,$class, [switch]$help)

Function GetHelp()
{
  $helpText= '
@"
 DESCRIPTION:
 NAME: BrowseActiveDirectorySchema.ps1
 Browse Active Directory Schema. Lists Classes, and properties. 

 PARAMETERS: 
 -Action <L(ist all classes), M(andatory), O(ptional), F(ind)>
 -Class class to search: user, computer, person, contact etc
 -Help displays this help topic

 SYNTAX:
 BrowseActiveDirectorySchema.ps1 -A L
 Lists the name of each class defined in the AD schema

 BrowseActiveDirectorySchema.ps1 -A M -c user
 Lists the mandatory properties of the user class

 BrowseActiveDirectorySchema.ps1 -A O -c computer
 Lists the optional properties of the computer class

 BrowseActiveDirectorySchema.ps1 -A F -c user
 Lists all Active Directory Classes that contain the word user 
 in the actual class name

 BrowseActiveDirectorySchema.ps1 -Action Find -c user
 Lists all Active Directory Classes that contain the word user 
 in the actual class name

 BrowseActiveDirectorySchema.ps1 -help
 Prints the help topic for the script
"@ #end helpText
  $helpText
} #end GetHelp
Function GetADSchema($Action, $class)
{
 $schema = [DirectoryServices.ActiveDirectory.ActiveDirectorySchema]::GetCurrentSchema()
 Switch ($Action)
  {
   "classes" { 
              $schema.FindAllClasses() | 
              Select-Object -Property Name 
             }
   "Mandatory" 
             {
              "Mandatory Properties of $class object"
              ($schema.FindClass("$class")).MandatoryProperties | 
               Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
             }
   "Optional" 
             {
              "Optional Properties of $class object"


              "This might take a few seconds ..."
              ($schema.FindClass("$class")).OptionalProperties | 
              Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
             }
   "Find" 
             {
              $schema.FindAllClasses() | 
              Where-Object { $_.name -match "$class" } |
              Select-Object -property name
             }
   DEFAULT {"$action is not a valid action." ; GetHelp ; Exit}
  }
} #end GetADSchema

Function GetAllClasses()
{
 GetAdSchema("classes")
} #end GetAllClasses

Function GetMandatory($class)
{
 GetAdSchema -action "Mandatory"  -class $class 
} #end GetMandatory

Function GetOptional($class)
{
 GetAdSchema -action "Optional"  -class $class 
} #end GetOptional

Function FindClasses($class)
{
 GetAdSchema -action "Find" -class $class
} #end FindClasses
# *** Entry Point to Script ***
if($help) { GetHelp ; Exit }

Switch ($action)
{
 "L" {GetAllClasses ; Exit}
 "M" {GetMandatory($class) ; Exit}
 "O" {GetOptional($class) ; Exit}
 "F" {FindClasses($class) ; Exit}
 DEFAULT { "$action is not a valid action." ; GetHelp ; Exit} 
}

ご覧のとおり、このスクリプトは Param ステートメントで始まります。このステートメントは、3 つのコマンド ライン パラメータを作成するために使用されます。これらのパラメータを使用すると、異なる動作を確認するためにスクリプトを編集する必要はなく、スクリプトの実行によってスクリプトを変更することができます。これは非常に便利です。

Param($action,$class, [switch]$help)

たとえば、Active Directory ドメイン サービス (AD DS) のユーザー クラスの必須プロパティを確認するには、–action M と –class user を指定します (図 2 参照)。

fig02.gif

図 2 ユーザー クラスの必須プロパティの表示

グループ クラスの省略可能なプロパティも、同じくらい簡単に選択することができます。このように、スクリプトを記述し直すのではなく実行時にスクリプトの動作を変更できるのが、コマンド ライン パラメータを使用するメリットです。これは、1 回しか使用しないスクリプトではなくユーティリティとして使用するつもりのスクリプトを記述する場合のベスト プラクティスです。

ヘルプを提供する

図 1 に示したスクリプトの、Param ステートメントの次のセクションは、GetHelp 関数を示しています。コマンド ライン パラメータを公開するスクリプトを記述する場合は、スクリプトの使用方法に関するヘルプを表示する関数を含めるのがベスト プラクティスです。記述したスクリプトのユーザーが、スクリプトで行われる処理を理解するためにスクリプトを開いて内容をすべて読まなければならないというのは望ましくありません。確かに、スクリプト設計の基本理念は "スクリプトは判読可能でなければならない" というものですが、ヘルプ機能を含めると、ユーザーの利便性が向上します。

GetHelp 関数を使用すると、Get-Help コマンドレットを使用した場合とほぼ同じように情報が表示されます。説明、パラメータ、構文という 3 つのセクションから成るテキストが表示されます。GetHelp は、2 つの処理を実行します。表示するテキストが含まれている here-string を作成し、here-string が格納されている変数 (この場合は $helpText) の中身を表示するという処理です。

here-string は Windows PowerShell 構文の 1 つで、これを使用すると、引用符の付け方に関する規則を気にせずに情報を入力し出力の書式を設定することができます。here-string 内に入力したものはすべて、テキストとして扱われます。GetHelp は、–help スイッチを指定してスクリプトが実行された場合、または、間違ったパラメータが入力された場合に呼び出されます。図 3 は、–help スイッチを指定してスクリプトを呼び出した結果を示しています。

fig03.gif

図 3 –help スイッチを指定してスクリプトを呼び出す

核心

GetHelp 関数の次にあるのは、GetADSchema 関数です。図 1 に示したスクリプトの実際の処理のほとんどを行うのがこの関数です。ここで重要なのは、Microsoft .NET Framework の DirectoryServices.ActiveDirectory.ActiveDirectorySchema クラスを使用することです。クラスを角かっこで囲み、その後にコロンを 2 つ記述すると、そのクラスの静的メソッド (この場合は GetSchema と GetCurrentSchema) にアクセスすることができます。

静的メソッド GetCurrentSchema は、現在接続されているスキーマを表す ActiveDirectorySchema クラスのインスタンスを返します。図 4 は、ActiveDirectorySchema クラスのメンバを示しています。

fig04.gif

.NET Framework の DirectoryServices.ActiveDirectory.ActiveSchema クラスのインスタンスを作成し、取得したスキーマ オブジェクトを $schema 変数に格納したら、どのアクションを実行するかを決める必要があります。これを行うには、Switch ステートメントで、$action 変数から渡された値を評価します。

GetADSchema 関数では、満たされた条件に応じて、AD DS 内のすべてのクラスを探し出したり、特定のクラスの必須プロパティまたは省略可能なプロパティを表示したり、特定の条件を満たすクラスを探し出したりします。Switch を使用する場合は、必ず既定の条件を含めるのがベスト プラクティスです。

ヘルパ関数

コードの一部を分割し、スクリプトを拡張しやすくするために、実行時にスクリプトに渡されたパラメータに応じて呼び出されるいくつかのヘルパ関数を含めました。各ヘルパ関数では、GetADSchema を呼び出し、コマンド ラインから –action パラメータ用に渡された値に応じて異なるパラメータ セットを渡します。

1 つ目のヘルパ関数は GetAllClasses です。この関数では、GetADSchema を呼び出し、"classes" という単語を渡します。GetADSchema 関数内の Switch ステートメントで文字列 "classes" に一致すると、ActiveDirectorySchema クラスの FindAllClasses メソッドが呼び出されます。Switch ステートメントによって呼び出されるコードを以下に示します。

"classes" { 
              $schema.FindAllClasses() | 
              Select-Object -Property Name'

GetAllClasses 関数を以下に示します。

Function GetAllClasses()
{
GetADSchema("classes")
} #end GetAllClasses

次のヘルパ関数は GetMandatory です。この関数の目的は、スクリプトの実行時に –class パラメータで指定されたオブジェクトの必須プロパティを返すことです。GetMandatory 関数は、–class パラメータを通じてコマンド ラインから $class の値を受け取ります。GetMandatory では、GetADSchema 関数を呼び出す際に 2 つのパラメータを渡します。2 つのパラメータを渡すので、両方とも完全なパラメータ名を指定して、コードを読みやすく理解しやすいものにするのがベスト プラクティスだと思います。一方、GetAllClasses 関数では、GetADSchema 関数を呼び出す際に –action というパラメータ名は使用せず、前後関係によってどのパラメータ用の値であるかが判断される形式で値 "classes" を渡しています。

GetADSchema 関数が呼び出されると、この関数では、ActiveDirectorySchema クラスの FindClass メソッドを使用して、$class 変数で指定されているクラスを取得します。そして、ActiveDirectorySchemaClass クラスのインスタンスを返します。このクラスのメンバを図 5 に示します。

fig05.gif

GetADSchema 関数では、次に、オブジェクトの MandatoryProperties プロパティを照会し、結果を Format-Table コマンドレットにパイプラインします。ここでは、Name プロパティ、Syntax プロパティ、および IsSingleValued プロパティが選択されています。Format-Table コマンドレットのスイッチ パラメータ –Autosize を指定すると、プロパティ値が途中までしか表示されないという事態を避けるために、可能であれば列のサイズが自動的に調整されます。文字列 "Mandatory" と一致した場合に実行されるコードを以下に示します。

"Mandatory" 
       {
       "Mandatory Properties of $class object"
       ($schema.FindClass("$class")).MandatoryProperties | 
       Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
       }

GetMandatory 関数を以下に示します。

Function GetMandatory($class)
{
 GetAdSchema -action "Mandatory" -class $class 
} #end GetMandatory

では、GetOptional 関数で AD DS クラスの省略可能なプロパティを表示する方法を見ていきましょう。GetOptional は、–class パラメータを通じてコマンド ラインから $class 値を受け取り、GetADSchema 関数に "Optional" という名前のアクションと共に $class 値を渡します。

Switch ステートメントで文字列 "Optional" と一致すると、省略可能なプロパティの表示には数秒かかる場合があることを説明するメッセージが画面に表示されます。続いて、ActiveDirectorySchema クラスの FindClass メソッドが呼び出されます。FindClass メソッドは ActiveDirectorySchemaClass クラスのインスタンスを返します。ActiveDirectorySchemaClass クラスの OptionalProperties プロパティを照会した場合は、AD DS 内の選択されたクラス用に定義されている省略可能なプロパティが返されます。

結果は Format-Table コマンドレットにパイプラインされ、このコマンドレットにより、必須プロパティの場合と同じ形式で情報が表示されます。この一連の処理を行うコード セクションを以下に示します。

"Optional" 
      {
      "Optional Properties of $class object"
      "This might take a few seconds ..."
      ($schema.FindClass("$class")).OptionalProperties | 
      Format-Table -Property Name, Syntax, IsSingleValued -AutoSize 
      }

以下のコードは、GetOptional 関数の全容です。

Function GetOptional($class)
{
 GetAdSchema -action "Optional"  -class $class 
} #end GetOptional

最後のヘルパ関数は FindClasses です。この関数では、GetADSchema 関数を呼び出し、2 つの値を渡します。1 つ目はアクション Find で、2 つ目は探し出すクラスです。この関数の目的は、AD DS スキーマ内のクラスのうち、さらなる調査を行う価値がある可能性のあるクラスをユーザーが特定するのを支援することです。

電子メールについて調査する必要があるとします。その場合、どのクラスが電子メールに関連しているかを確認してから、当該のクラスにどのようなプロパティが存在するかを確認する必要があるでしょう。図 6 に示すように、まず、–action f パラメータと –class mail パラメータを指定してスクリプトを実行します。これにより、名前のどこかに文字列 "mail" が含まれているクラスがすべて返されます。調査対象のクラスを特定したら、そのクラスのプロパティを調べます。これを行うには、アクション m ("必須" を意味する "mandatory" を表します) を選択し、–c ("class" を表します) パラメータを指定して、その後に具体的なクラス名を指定します。

fig06.gif

図 6 AD DS スキーマ内のクラスを探し出す

FindClasses 関数で GetADSchema を呼び出すと、FindAllClasses メソッドが呼び出され、このメソッドが返す ActiveDirectorySchemaClass クラスのコレクションがパイプラインに渡されます。Where-Object では、正規表現パターン マッチを使用して、$class 変数に格納されている値と一致するクラスを探します。コードを以下に示します。

"Find" 
    {
    $schema.FindAllClasses() | 
    Where-Object { $_.name -match "$class" } |
    Select-Object -property name

FindClasses 関数を以下に示します。

Function FindClasses($class)
{
 GetAdSchema -action "Find" -class $class
} #end FindClasses

すべてのヘルパ関数の定義後に、スクリプトへのエントリ ポイントが用意されています。エントリ ポイントで行っているのは、コマンド ラインを確認し、呼び出す関数を決めるというたった 1 つの処理です。最初にチェックされているのは、–help パラメータが存在するかどうかです。–h または –help を指定してスクリプトが実行されている場合は、以下のように、GetHelp 関数が呼び出されてヘルプが表示されてからスクリプトは終了します。

if($help) { GetHelp ; Exit }

最初に –help パラメータの有無が確認されるので、このパラメータがコマンド ラインで指定されているかどうかが他の何よりも優先されます。–help パラメータが使用されていない場合、スクリプトでは、既定のパラメータである –action パラメータ用に渡された値を評価する必要があります。–action 以外のパラメータが使用されていない場合、コマンド ラインに入力されたものはすべて、–action パラメータ用の値であると解釈されます。これには、スクリプトへの無効な入力を把握できるというメリットもあります。

Switch ステートメントは、–action 用に渡された値を評価するのにうってつけの手段です。4 つのアクションが定義されており、それぞれのアクションに対応する関数が呼び出されます。5 番目に定義されている条件は既定のアクションで、このアクションでは、当該のアクションは許可されていないという旨のメッセージが表示され、GetHelp 関数が呼び出されます。

Switch ステートメントについて 1 つ覚えておく必要があるのは、このステートメントでは複数の一致を検出できるということです。そのため、それぞれの関数呼び出しの後に Exit ステートメントが使用されています。Switch ステートメントのコードを以下に示します。

Switch ($action)
{
 "L" {GetAllClasses ; Exit}
 "M" {GetMandatory($class) ; Exit}
 "O" {GetOptional($class) ; Exit}
 "F" {FindClasses($class) ; Exit}
 DEFAULT { "$action is not a valid action." ; GetHelp ; Exit} 
}

まあ、こんなところです、皆さん。ADSI Scriptomatic 以外に Active Directory ブラウザはありません。ですが、当面は BrowseActiveDirectorySchema.ps1 スクリプトがお役に立つでしょう。Active Directory スクリプトに関するその他の楽しい情報については、Active Directory スクリプトの拠点となるページを参照してください。また、ご存じのとおり、スクリプト センターは年中無休で営業しています。

Ed Wilson はマイクロソフトのシニア コンサルタントであり、有名なスクリプトの専門家です。マイクロソフト認定トレーナーでもあり、彼が世界中のマイクロソフト プレミア サポートの顧客向けに開催している Windows PowerShell のワークショップは好評です。これまでに Windows スクリプトに関するいくつかの書籍を含む 8 冊の書籍を執筆し、その他にも多くの書籍の執筆に携わっています。Ed は 20 種類を超えるこの業界の資格を持っています。

Craig Liebendorfer は言葉を巧みに操る、マイクロソフトのベテラン Web 編集者です。Craig は毎日言葉にかかわって給料を受け取ることができる仕事が存在することが、いまだに信じられないと思っています。彼が大好きなことの 1 つは場違いなユーモアなので、まさにこのコラムにうってつけの人物です。彼は自分の立派な娘が、自分の人生における最も偉大な功績であると考えています。