Active Directory データのプロパティ出力の COM 対応版について、変更点の説明です。
今回は大きい整数に関係する部分についてです。(コードはこちら VB C#)
まずは呼出し側です。
通常のプロパティ出力(OutputProperties)もオプションのプロパティ出力(OutputOptionalProperties)もプロパティ名(属性)の数だけループしてます。
プロパティは DirectoryEntry.Properties.Item(プロパティ名) で取得でき、型は PropertyValueCollection です。
プロパティは値を複数持つものもあるのでコレクションになってます。
値は PropertyValueCollection.Value で取得でき、型は Object です。この値は、コレクションの要素の数が 0 だと null 参照、1 つだとその要素の値、複数だと各要素の値の配列(のコピー)になります。
大きい整数かどうかは この値の型が IADsLargeInteger かどうかで判断してます。
大きい整数の場合はその値を取得する GetLargeIntegerValue メソッドを呼び出してます。引数はプロパティ(属性)名とその値(IADsLargeInteger)です。
次は大きい整数値を取得する GetLargeIntegerValue メソッド側です。
大きい整数(LargeInteger)の属性のとこで書きましたが、"大きい整数" の属性の値は整数で表されるものと日付で表わされるものとがあるので、属性とその値によってどのような値を返すかが変わってきます。
最初に IADsLargeInteger 型の value パラメータの値を Int64 に変換してます。
IADsLargeInteger インターフェイスのメンバは HighPart プロパティと LowPart プロパティの 2 つです。(型は Int32)
Int64 への変換は HighPart プロパティと LowPart プロパティの値を 8 桁の 16 進文字列にして連結し、それを Convert.ToInt64 メソッドで行ってます。
※MSDN ライブラリ 標準の数値書式指定文字列 - 16 進数 ("X") 書式指定子、Convert.ToInt64 メソッド (String, Int32)
C# の方は次のコードをコメントアウトしてます。
var lval = (long)((uint)value.LowPart + (((long)value.HighPart) << 32));
このコードは MSDN ライブラリの「大きい整数のプロパティ型」に載ってるんですが、VB でこれに相当するコードだと LowPart プロパティが負の値の時に OverflowException がスローされるので、同じやり方ができる今のコードにしました。(符号なしの型は CLS に準拠してないですし・・・という言い訳)
この変換した値とプロパティ(属性)名でどのような値を返すか決めます。
まずはプロパティ(属性)名が lockoutTime かどうかを判断してます。
コメントには「ロックアウトしたことがある時」と書いてますが意味は同じです。というのもロックアウトしたことがなければ値がないので、このメソッドが呼び出されることはないからです。
※DirectoryEntry.Properties には 値のないプロパティは含まれません。
ロックアウトしたことがある時は、変換した値が 0 より大きければ その値とそれを日付にしたものを文字列にして返してます。そうでなければ変換した値(0)を返してます。
※理由は lockoutTime属性の値の確認をご覧ください。
次に IsInteger メソッドを呼び出して、プロパティ(属性)が整数を表すものかどうかを確認してます。
整数を表すプロパティ(属性)であれば変換した値を返してます。
その次に変換した値が 0 か最大値(Int64.MaxValue)なら文字列「(なし)」を返してます。
最後、どれにも該当しないプロパティ(属性)は日付を表すものなので、変換した値を DateTime.FromFileTime メソッドで現地時刻に変換して返してます。
Int64 に変換した値は 100 ナノ秒(ns)刻みで表したファイル時刻を表しているので、このメソッドで欲しい時刻を得ることができます。
また、1601/1/1 を起点として 100 ナノ秒刻みの経過時間を加算して現地時刻に変換しても同じ結果を得ることができます。
※コメント部分 VB : #1/1/1601#.AddTicks(lval).ToLocalTime() C# : new DateTime(1601, 1, 1).AddTicks(lval).ToLocalTime()
すべての属性について値を確認できたわけではないので怪しいとこもあるかもしれませんが、よく使いそうな属性についてはカバーできるんじゃないかなぁと思います。