グループのリストもユーザのリストと同じでローカル用も考慮して実装します。
まずは実行時の画面。左がドメインログオン時で右がローカルログオン時。(クリックすると新しいウィンドウで拡大図が表示されます。)
実装はこんな感じ。
プライベートフィールド
Private ReadOnly groups As IEnumerable(Of IGroup) 'グループのリスト
'プライマリグループのメンバ格納用(グループのPrimaryGroupToken, メンバのパスとオブジェクトの種類のリスト)
Private ReadOnly primaryGroupMembers As Dictionary(Of Integer, Dictionary(Of String, CategoryType))
Private ReadOnly groupBindingSource As BindingSource
コンストラクタ
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
groups = DirectoryAccess.GetGroups() 'グループのリストを取得
If DirectoryAccess.IsLogonDomain Then 'ドメインにログオンしている時
Dim domainGroups As New List(Of DomainGroup)
For Each group As DomainGroup In groups
domainGroups.Add(group)
Next
groupBindingSource = Me.DomainGroupBindingSource
groupBindingSource.DataSource = domainGroups
Me.pnl_local.Visible = False
Else 'ドメインにログオンしていない時
Dim localGroups As New List(Of LocalGroup)
For Each group As LocalGroup In groups
localGroups.Add(group)
Next
groupBindingSource = Me.LocalGroupBindingSource
groupBindingSource.DataSource = localGroups
Me.pnl_domain.Visible = False
Me.lbox_group.Height -= 96
Me.Height -= 166
End If
Me.DescriptionTextBox.DataBindings.Add("Text", groupBindingSource, "Description")
Me.lbox_group.Items.AddRange(groups.ToArray()) 'グループのリストボックスにグループを追加
primaryGroupMembers = New Dictionary(Of Integer, Dictionary(Of String, CategoryType))()
Me.lbl_count.Text = String.Format("{0} 個のオブジェクト", groupBindingSource.Count)
Me.lbox_group.SelectedIndex = groupBindingSource.Position
Call ShowRelatingInfo() '関連情報を表示
End Sub
イベントハンドラ
Private Sub lbox_group_SelectedIndexChanged(
sender As Object, e As EventArgs) Handles lbox_group.SelectedIndexChanged
'選択されている項目を選択してもイベントが発生する
If groupBindingSource.Position = Me.lbox_group.SelectedIndex Then
Return
End If
groupBindingSource.Position = Me.lbox_group.SelectedIndex
Call ShowRelatingInfo() '関連情報を表示
End Sub
プライベートメソッド
Private Sub ShowRelatingInfo() '関連情報を表示
Dim group = DirectCast(groupBindingSource.Current, IGroup) '選択されたグループ
If DirectoryAccess.IsLogonDomain Then 'ドメインにログオンしている時
Call ShowDomainMembers(group.Native) 'ドメイングループのメンバを表示
Call ShowBelongGroups(group.Native) '所属するグループを表示
Else 'ドメインにログオンしていない時
Call ShowLocalMembers(group.Native) 'ローカルグループのメンバを表示
End If
End Sub
Private Sub ShowDomainMembers(group As IADsGroup) 'ドメイングループのメンバを表示
Dim subItem(1) As String '名前と所属パスの配列
Dim objectType As CategoryType 'ディレクトリ オブジェクトの種類
Me.lv_member.Items.Clear()
For Each member As IADs In group.Members()
subItem(0) = DirectoryAccess.PathToCn(member.Name) '名前を取得
subItem(1) = DirectoryAccess.GetBelongPath(member) '所属パスを取得
[Enum].TryParse(Of CategoryType)(member.Class, True, objectType)
Call AddListViewItem(Me.lv_member, subItem, True, objectType) 'リストビューにアイテムを追加
Next
Call AddPrimaryGroupMembers() 'プライマリグループになっているメンバを追加
End Sub
Private Sub AddListViewItem(lView As ListView, subItem() As String, showImage As Boolean,
Optional objectCategory As CategoryType = CategoryType.User) 'リストビューにアイテムを追加
Dim listItem As ListViewItem
If showImage Then 'イメージを表示する時
listItem = New ListViewItem(subItem, objectCategory)
Else 'イメージを表示しない時
listItem = New ListViewItem(subItem)
End If
listItem.SubItems.AddRange(subItem)
lView.Items.Add(listItem)
End Sub
Private Sub AddPrimaryGroupMembers() 'プライマリグループになっているメンバを追加
Dim group = DirectoryAccess.GroupTokens.ElementAt(groupBindingSource.Position) '選択したグループ
'プライマリグループのメンバ(パスとオブジェクトの種類のリスト)
Dim primaryMembers As Dictionary(Of String, CategoryType) = Nothing
If primaryGroupMembers.TryGetValue(group.Key, primaryMembers) Then '格納済の時
If primaryMembers.Count = 0 Then
Return
End If
Else '未格納の時
‘指定した PrimaryGroupToken を持つグループをプライマリグループとしているメンバの DirectoryEntry のリスト
Dim primaryMemberEntries = DirectoryAccess.GetPrimaryGroupMemberEntries(group.Key)
primaryMembers = New Dictionary(Of String, CategoryType)(primaryMemberEntries.Count)
primaryGroupMembers.Add(group.Key, primaryMembers)
If primaryMemberEntries.Count = 0 Then
Return
End If
For Each user In primaryMemberEntries
primaryMembers.Add(user.Path,
DirectCast([Enum].Parse(GetType(CategoryType), user.SchemaClassName, True), CategoryType))
user.Close()
Next
End If
Dim subItem(1) As String '名前と所属パスの配列
For Each member In primaryMembers
subItem(0) = DirectoryAccess.PathToCn(member.Key) '名前を取得
subItem(1) = DirectoryAccess.GetBelongPath(member.Key) '所属パスを取得
Call AddListViewItem(Me.lv_member, subItem, True, member.Value) 'リストビューにアイテムを追加
Next
End Sub
Private Sub ShowBelongGroups(group As IADsGroup) '所属するグループを表示
Dim groupObjects As Object '所属するグループ
Me.lv_group.Items.Clear()
Try
groupObjects = group.GetEx("memberOf")
Catch '所属するグループがない
Return
End Try
Dim subItem(1) As String '名前と所属パスの配列
For Each groupObject As String In DirectCast(groupObjects, IEnumerable)
subItem(0) = DirectoryAccess.PathToCn(groupObject) '名前を取得
subItem(1) = DirectoryAccess.GetBelongPath(groupObject) '所属パスを取得
Call AddListViewItem(Me.lv_group, subItem, False) 'リストビューにアイテムを追加
Next
End Sub
Private Sub ShowLocalMembers(group As IADsGroup) 'ローカルグループのメンバを表示
Dim memberName As String
Me.lbox_member.Items.Clear()
For Each member As IADs In group.Members()
memberName = GetLocalMemberName(member) 'ローカルのメンバ名を取得
Me.lbox_member.Items.Add(memberName)
Next
End Sub
Private Function GetLocalMemberName(member As IADs) As String 'ローカルのメンバ名を取得
If TypeOf member Is IADsUser Then 'ユーザの時
Return member.ADsPath.Substring(member.ADsPath.LastIndexOf("/"c) + 1)
Else 'グループの時
Return member.ADsPath.Substring(8).Replace("/"c, "\"c)
End If
End Function
デザイナファイルの Dispose メソッド内の components.Dispose() の下に次のコードを追記
DirectoryAccess.DisposeItems(groups)
ShowBelongGroups メソッドの Try ブロック内で GetEx メソッドを呼んでます。
このメソッドは IADs インターフェイスで定義されてます。似たようなメソッドに Get メソッドがあります。
Get メソッドも GetEx メソッドも指定した名前のプロパティ値を取得します。戻り値の型は Object 型ですが次の違いがあります。
Get メソッドは、値が 1つしかないプロパティの場合は単一の値を返し、値が複数あるプロパティの場合は配列を返します。
GetEx メソッドは値が 1つしかないプロパティでも値が複数あるプロパティでも配列を返します。
値が複数あるプロパティには次のようなものがあります。
・ユーザ、グループ、コンピュータが所属するグループ(上記 memberOf)
・グループのメンバ(member)
・プリンタの利用可能な用紙(printMediaSupported)
・共有フォルダのキーワード(keywords)
値が 1つしかないと判ってるプロパティの取得なら Get メソッドを呼べばループ処理は要らないですね。
おまけ
Office 製品で Visual Basic Editor を表示する時は Alt + F11。