前回書いた Active Directoryデータのプロパティ出力の C# のコードです。
private void OutputProperties(DirectoryEntry entry, string filePath)
{
var props = entry.Properties.PropertyNames.Cast<string>().OrderBy(s => s).ToList(); //プロパティ名のリスト
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
foreach (var pname in props) //プロパティ数分
{
var val = entry.Properties[pname].Value;
if (val is byte[]) //バイト配列の時
{
var pstr = GetByteValue(pname, (byte[])val); //値を取得
writer.WriteLine("{0}:{1}", pname, pstr);
}
else //バイト配列以外の時
{
foreach (var pval in entry.Properties[pname]) //値数分
{
writer.WriteLine("{0}:{1}", pname, pval);
}
}
}
}
}
private void OutputOptionalProperties(DirectoryEntry entry, string filePath)
{
var adsi = (IADs)entry.NativeObject; //ADSI オブジェクト
var schema = (IADsClass)entry.SchemaEntry.NativeObject; //スキーマ オブジェクト
object val;
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
adsi.GetInfoEx((object[])schema.OptionalProperties, 0); //プロパティの値をディレクトリ ストアから読込
foreach (string pname in (IEnumerable)schema.OptionalProperties) //オプションのプロパティ数分
{
try
{
val = adsi.GetEx(pname);
}
catch
{
writer.WriteLine("{0}:<未設定>", pname);
continue;
}
if (val is byte[]) //バイト配列の時
{
var bstr = BitConverter.ToString((byte[])val);
writer.WriteLine("{0}:{1}", pname, bstr);
}
else //バイト配列以外の時
{
foreach (var pval in (IEnumerable)val) //値数分
{
if (pval is byte[]) //バイト配列の時
{
var pstr = GetByteValue(pname, (byte[])pval); //値を取得
writer.WriteLine("{0}:{1}", pname, pstr);
}
else //バイト配列以外の時
{
writer.WriteLine("{0}:{1}", pname, pval);
}
}
}
}
}
}
//値を取得
private string GetByteValue(string name, byte[] value)
{
if (name.Equals("objectSid"))
{
return new SecurityIdentifier(value, 0).ToString();
}
else if (name.Equals("objectGUID"))
{
return new Guid(value).ToString();
}
else
{
return BitConverter.ToString(value);
}
}
OutputOptionalProperties メソッドの try ブロック内で IADs.GetEx メソッドを呼び出して、指定したプロパティ(属性)の値を取得してます。
戻り値は object 型の変数に入れてるんですが、戻り値は dynamic 型です。IADs.Get メソッドも同様です。
VB は Object 型だから C# も同じだと思ってましたが違うんですね。
サンプルでは型の互換性チェックとキャストで使ってるだけなので気にすることはないと思いますが。
でもパフォーマンスは悪いですよ。(理由はこちらを)
プロパティの値を読み込んでるので OutputProperties メソッド同様、DirectoryEntry.Properties プロパティから値を取得するようにすれば、構造化例外処理の代わりに null チェックをすればOK のはず。
近いうちに確認してみます。