Active Directoryデータのプロパティ出力の COM 対応版の C# のコードです。
※2013/12/10 Trustee はユーザやグループの名前部分のみ出力、AceType は値とその列挙体文字列を出力するよう修正しました。
※2013/12/11 GetValue メソッドの name パラメータを削除しました。
以前からの変更点は VB のコードの方に書いてます。
public static 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 if (val is IADsSecurityDescriptor) //セキュリティ記述子の時
{
var sd = (IADsSecurityDescriptor)val;
var aceGroups = ((IADsAccessControlList)sd.DiscretionaryAcl).Cast<IADsAccessControlEntry>().OrderBy(
ace => System.IO.Path.GetFileName(ace.Trustee)).ThenBy(ace => ace.AccessMask).ThenBy(ace => ace.AceFlags).ThenBy(
ace => ace.AceType).ThenBy(ace => ace.Flags).GroupBy(ace => String.Format("{0}|{1}|{2}|{3}|{4}",
ace.Trustee, ace.AccessMask, ace.AceFlags, ace.AceType, ace.Flags)).ToList(); //プロパティ値でグループ化したACE
var ctr = 0;
writer.WriteLine(pname);
foreach (var aceGroup in aceGroups) //ACE数分
{
var ace = aceGroup.First();
ctr++;
writer.WriteLine(" {0:D2}. Trustee :{1}", ctr, System.IO.Path.GetFileName(ace.Trustee));
writer.WriteLine(" {0:D2}. AccessMask:{1}", ctr, ToEnumValueText(ace.AccessMask, typeof(ADS_RIGHTS_ENUM)));
writer.WriteLine(" {0:D2}. AceFlags :{1}", ctr, ToEnumValueText(ace.AceFlags, typeof(ADS_ACEFLAG_ENUM)));
writer.WriteLine(" {0:D2}. AceType :{1}", ctr, ToEnumValueText(ace.AceType, typeof(ADS_ACETYPE_ENUM)));
writer.WriteLine(" {0:D2}. Flags :{1}", ctr, ToEnumValueText(ace.Flags, typeof(ADS_FLAGTYPE_ENUM)));
}
}
else if (val is IADsLargeInteger) //大きい整数の時
{
var li = GetLargeIntegerValue(pname, (IADsLargeInteger)val); //大きい整数値を取得
writer.WriteLine("{0}:{1}", pname, li);
}
else //それ以外の時
{
foreach (var pval in entry.Properties[pname]) //値数分
{
var value = GetValue(pval); //値を取得
writer.WriteLine("{0}:{1}", pname, value);
}
}
}
}
}
public static void OutputOptionalProperties(DirectoryEntry entry, string filePath)
{
var schema = (IADsClass)entry.SchemaEntry.NativeObject; //スキーマ オブジェクト
var props = (object[])schema.OptionalProperties; //オプションのプロパティ
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
entry.Invoke("GetInfoEx", props, 0); //プロパティをディレクトリ ストアから読込
foreach (string pname in props) //オプションのプロパティ数分
{
var pvcol = entry.Properties[pname]; //PropertyValueCollection
if (pvcol.Value == null) //値がない時
{
writer.WriteLine("{0}:<未設定>", pname);
continue;
}
if (pvcol.Value is byte[]) //バイト配列の時
{
var bstr = GetByteValue(pname, (byte[])pvcol.Value); //バイト値を取得
writer.WriteLine("{0}:{1}", pname, bstr);
}
else if (pvcol.Value is IADsLargeInteger) //大きい整数の時
{
var li = GetLargeIntegerValue(pname, (IADsLargeInteger)pvcol.Value); //大きい整数値を取得
writer.WriteLine("{0}:{1}", pname, li);
}
else //それ以外の時
{
foreach (var pval in pvcol) //値数分
{
if (pval is byte[]) //バイト配列の時
{
var pstr = GetByteValue(pname, (byte[])pval); //バイト値を取得
writer.WriteLine("{0}:{1}", pname, pstr);
}
else //バイト配列以外の時
{
var value = GetValue(pval); //値を取得
writer.WriteLine("{0}:{1}", pname, value);
}
}
}
}
}
}
//バイト値を取得
private static 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);
}
}
//大きい整数値を取得
private static object GetLargeIntegerValue(string name, IADsLargeInteger value)
{
//var lval = (long)((uint)value.LowPart + (((long)value.HighPart) << 32));
var lval = Convert.ToInt64(value.HighPart.ToString("x8") + value.LowPart.ToString("x8"), 16);
if (name.Equals("lockoutTime")) //ロックアウトしたことがある時
{
if (lval > 0) //ロックアウト中又はロックアウト期間が過ぎただけの時
{
return String.Format("{0}({1})", lval, DateTime.FromFileTime(lval)); //判り易いよう日付も付ける
}
return lval; //明示的にロック解除又はロックアウト期間が過ぎてログオン成功しているので値は0
}
if (IsInteger(name, lval)) //整数の時
{
return lval;
}
if ((lval == 0) || (lval == Int64.MaxValue))
{
return "(なし)";
}
return DateTime.FromFileTime(lval); //eq. new DateTime(1601, 1, 1).AddTicks(lval).ToLocalTime()
}
//整数かどうか
private static bool IsInteger(string name, long value)
{
if (name.Equals("maxStorage"))
{
return true;
}
if (name.StartsWith("msDS-"))
{
return false;
}
if (name.StartsWith("uSN"))
{
return true;
}
return false;
}
//値を取得
private static object GetValue(object value)
{
if ((value is DateTime) == false) //日付ではない時
{
return value;
}
var d = Convert.ToDateTime(value);
return d.Date.Equals(new DateTime(1601, 1, 1)) ? d : d.ToLocalTime();
}
//列挙体のプロパティ値をテキスト化
private static string ToEnumValueText(int value, Type enumType)
{
if (enumType == typeof(ADS_ACETYPE_ENUM))
//AceTypeの時
{
return String.Format("{0}({1})",
value, Enum.ToObject(enumType, value));
}
Func<int, string> selector = e => Enum.ToObject(enumType, e).ToString();
var values = Enum.GetValues(enumType).Cast<int>().Where(
e => (value & e) == e).OrderBy(selector).Select(selector).ToList(); //設定されている値の列挙体文字列
if (values.Count == 0) //設定されている値がない時
{
return value.ToString();
}
return String.Format("{0}({1})", value, String.Join(" | ", values));
}