ドメインユーザを表す DomainUser クラスのデータバインド用のメソッドから呼び出してる DirectoryAccess クラスのメソッドです。
先にVBのコードを。
※引数チェックは省略します。
'指定した名前と種類の Directory オブジェクトを検索します。
Public Shared Function FindDirectoryObject(name As String, objectCategory As CategoryType) As DirectoryObject
Using root = GetRootEntry() 'ルートのDirectoryEntryを取得 参考:ユーザやグループの検索
If CanConnectDomain Then 'ドメインに接続できる時
Dim filter As String
Select Case objectCategory
Case CategoryType.User
filter = String.Format("(&(objectCategory={0})(sAMAccountName={1}))", objectCategory, name)
Case CategoryType.PrintQueue
filter = String.Format("(&(objectCategory={0})(printerName={1}))", objectCategory, name)
Case Else
filter = String.Format("(&(objectCategory={0})(name={1}))", objectCategory, name)
End Select
Using searcher As New DirectorySearcher(root, filter)
Dim result = searcher.FindOne()
Return If(result Is Nothing, Nothing, CreateInstance(result.GetDirectoryEntry()))
End Using
Else 'ドメインに接続できない時 <-- こっちはローカル
Return CreateInstance(root.Children.Find(name, objectCategory.ToString()))
End If
End Using
End Function
'ユーザの所属するグループを取得します。
Public Shared Function GetBelongGroups(user As IUser) As ReadOnlyCollection(Of String)
Dim groups As New List(Of String)()
For Each group As IADs In user.Native.Groups() '所属するグループ数分(プライマリ グループ以外)
groups.Add(group.Get("cn").ToString()) 'IADs.Get メソッドで cn の値を取得
Next
If TypeOf user Is DomainUser Then 'ドメインユーザの時
Dim primaryGroupId = DirectCast(user, DomainUser).PrimaryGroupId
groups.Add(GroupTokens.Item(primaryGroupId))
'GroupTokens プロパティ:IDictionary(Of Integer, String) は下のLoadGroupTokens メソッド内で要素がセットされます。
End If
groups.Sort()
Return groups.AsReadOnly()
End Function
'ユーザを取得します。
Public Shared Function GetUsers(Of T As {DirectoryObject, IUser})() As IList(Of T)
Dim users As New List(Of T)()
Using root = GetRootEntry() 'ルートのDirectoryEntryを取得
If CanConnectDomain Then 'ドメインに接続できる時
Dim filter = String.Format("(objectCategory={0})", CategoryType.User)
Using searcher As New DirectorySearcher(root, filter)
Using results = searcher.FindAll()
For Each res As SearchResult In results
users.Add(DirectCast(CreateInstance(res.GetDirectoryEntry()), T))
Next
End Using
If GroupTokens.Count = 0 Then 'ドメイングループのPrimaryGroupTokenと名前の組のリストがない時
LoadGroupTokens(searcher) 'ドメイングループのPrimaryGroupTokenと名前の組のリストをロード
End If
End Using
Else 'ドメインに接続できない時 <-- こっちはローカル
root.Children.SchemaFilter.Add(CategoryType.User.ToString())
For Each entry As DirectoryEntry In root.Children
users.Add(DirectCast(CreateInstance(entry), T))
Next
End If
End Using
Return users
End Function
'DirectoryObject のインスタンスを作成します。
Private Shared Function CreateInstance(entry As DirectoryEntry) As DirectoryObject
Dim category As CategoryType
If [Enum].TryParse(Of CategoryType)(entry.SchemaClassName, True, category) = False Then
Throw New ArgumentException("entry の種類が CategoryType に該当しません。", "entry")
End If
Select Case category
Case CategoryType.User
If CanConnectDomain Then 'ドメインに接続できる時
Return New DomainUser(entry)
Else 'ドメインに接続できない時
Return New LocalUser(entry)
End If
Case Else
Throw New NotImplementedException()
End Select
End Function
'ドメイングループの PrimaryGroupToken と名前の組のリストをロードします。
Private Shared Sub LoadGroupTokens(searcher As DirectorySearcher)
searcher.Filter = String.Format("(objectCategory={0})", CategoryType.Group)
Using results = searcher.FindAll()
For Each res As SearchResult In results
Dim entry = res.GetDirectoryEntry()
entry.Invoke("GetInfoEx", New Object() {"primaryGroupToken"}, 0)
Dim token = Convert.ToInt32(entry.Properties.Item("primaryGroupToken").Value)
GroupTokens.Add(token, entry.Properties.Item("cn").Value.ToString())
Next
End Using
End Sub
ユーザの所属するグループの取得に関する説明は別途書きます。