netからactive directoryデータにアクセス ~コンピュータ情報の取得と表示~
DESCRIPTION
Get computer objects from Active Directory and display on a windows/web form.TRANSCRIPT
![Page 1: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/1.jpg)
.NET から Active Directory データにアクセス
コンピュータ情報を表示する
小山 三智男mitchin
![Page 2: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/2.jpg)
2
サンプルアプリケーション
開発環境• OS : Windows 8 Enterprise(x64)• IDE : Visual Studio Professional 2013• アプリ: Windows フォーム (.NET 4.5.1)
Web フォーム (.NET 4.5.1) IE10クラスライブラリ (.NET 4.5.1)※ ソースコード自体は .NET 4 相当
実行環境• 単一ドメイン、単一サイト、単一サブネット• サーバ: Windows Server 2008 Standard SP2(.NET 4.5.1)• IIS : Windows 認証• クライアント: Windows 7 、 IE10
![Page 3: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/3.jpg)
3
参照設定
• .NET から Active Directory の色々な情報にアクセスするために System.DirectoryServices アセンブリを参照する必要があります。•ドメインやサイト関連は System.DirectoryServices. ActiveDirectory 名前空間にそれらを表すクラスがあり、 Active Directory の管理タスクを自動化するために使用されます。•Active Directory 内のデータにアクセスするために使用されるのは System.DirectoryServices 名前空間で、オブジェクトをカプセル化する DirectoryEntry クラスやクエリを実行するDirectorySearcher クラスなどがあります。•ADSI(Active Directory Services Interfaces) を使用してネイティブなオブジェクトを扱う場合は Active DS Type Libraryを参照する必要があります。
![Page 4: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/4.jpg)
4
主にどんなデータがあるの?
管理ツール「 Active Directory ユーザとコンピュータ」で管理する以下のオブジェクト• ユーザ• グループ• コンピュータ• 組織単位( OU)• プリンタ• 共有フォルダ
![Page 5: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/5.jpg)
5
サンプルアプリケーションの初期画面
ドメインを取得して画面下部に接続先を表示しています。
![Page 6: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/6.jpg)
6
コンピュータリスト画面( Windows アプリ)
![Page 7: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/7.jpg)
7
コンピュータリスト画面( Web アプリ)
![Page 8: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/8.jpg)
8
どうやって接続するの?
ドメインに接続するには LDAP を使います。プロバイダ: LDAP(Lightweight Directory Access Protocol)書式例: LDAP://DC=virtual,DC=proceed,DC=local
この LDAP の接続文字列を引数にして DirectoryEntry のインスタンスを作成します。この DirectoryEntry がドメインを表し、検索のルートになります。( DirectorySearcher の引数になります。)この場合、検索範囲はドメイン全体ということになります。
![Page 9: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/9.jpg)
9
検索してコンピュータのリストを取得する
• 接続するドメインや取得したコンピュータは DirectoryEntry オブジェクト
• ユーザやコンピュータを検索するのは DirectorySearcher オブジェクト• 複数の検索結果は SearchResultCollection として返される• SearchResult.GetDirectoryEntry メソッドで DirectoryEntry を取得• LDAP 書式のフィルター文字列( DirectorySearcher.Filter プロパティ)
は次のように指定(属性 = 値 をカッコで括る)• "(objectCategory=Computer)" -- コンピュータ• "(&(objectCategory=Computer)(!operatingSystem=Windows
8*))" -- Windows 8 以外のコンピュータ• "(&(objectCategory=Computer)(|(operatingSystem=Windows
Server*)(operatingSystem=Windows 8*)))" -- Windows Server か Windows 8 のコンピュータ• "(&(objectCategory=Computer)(logonCount>=100))" -- 100 回以
上ログオンしているコンピュータ
![Page 10: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/10.jpg)
10
ADSI のインターフェイス
基本インターフェイスは IADs インターフェイスで、各オブジェクトはこのインターフェイスを継承しています。
オブジェクトとそれに対応するインターフェイス
DirectoryEntry.NativeObject プロパティの値を上記インターフェイスにキャストできます。が・・・
ユーザ IADsUser
グループ IADsGroup
コンピュータ IADsComputer
組織単位( OU) IADsOU
プリンタ IADsPrintQueue
共有フォルダ
![Page 11: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/11.jpg)
11
IADsComputer の残念なお知らせ
IADsComputer インターフェイスは LDAP をサポートしていません。なのでキャストしようとすると InvalidCastException がスローされます。IADs インターフェイスにはキャストできますが、サンプルアプリケーションでは積極的に使用する理由がないので、今回追加したコンピュータを表すクラス(後述)にはユーザやグループを表すクラスのように ADSI オブジェクトを取得する Native プロパティを実装していません。
ユーザやグループについてはこちらのスライドを参照http://www.slideshare.net/mitchin227/display-userhttp://www.slideshare.net/mitchin227/display-group
![Page 12: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/12.jpg)
12
クラスライブラリ側に追加したクラス
Computer ( コンピュータを表すクラス )プロパティ• FullName (DNS 名を取得 )• OperatingSystem (OS を取得 )• OperatingSystemServicePack (OS の Service Pack を取得 )• OperatingSystemVersion (OS のバージョンを取得 )• PrimaryGroupId ( プライマリ グループ ID を取得 )• Role ( 役割を取得 )• Site ( サイトを取得 )
メソッド• FindByName ( コンピュータを検索 )• GetBelongGroups ( 所属するグループを取得 )• GetComputers ( コンピュータの一覧を取得 )
![Page 13: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/13.jpg)
13
クラスライブラリ側
DirectoryAccess クラスに追加したパブリックなメンバ• GetComputers メソッド ( コンピュータの一覧を取得 )
![Page 14: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/14.jpg)
14
フォーム側( Windows アプリ)
• BindingSource のデータソースに Computer クラスを指定• BindingSource を一覧 ListBox のデータソースに設定•詳細の各コントロールは BindingSource (クラス)のプロパティにバインド•グループの一覧を取得し、内部に保持•コンピュータの一覧を取得し BindingSource のデータソースに設定•取得したコンピュータの数を表示•選択されたコンピュータの所属するグループを取得し、所属するグループ ListBox のデータソースに設定
![Page 15: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/15.jpg)
15
フォーム側( Web アプリ)
• Computer クラスをビジネスオブジェクトとする ObjectDataSource を 3 つ用意• GetComputers メソッドを指定したものを一覧 ListBox のデータソースに指定• FindByName メソッドを指定したものを詳細 FormView のデータソースに指定(パラメーター ソースは一覧 ListBox )• GetBelongGroups メソッドを指定したものを所属するグループ ListBox のデータソースに設定•一覧 ListBox 用 ObjectDataSource の Selected イベントで取得したコンピュータの数を表示
![Page 16: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/16.jpg)
16
コンピュータ取得サンプルコード( VB )Public Shared Function GetComputers() As IList(Of Computer) Dim computers As New List(Of Computer)() Using root = GetRootEntry() ' ルートの DirectoryEntry を取得 Dim filter = String.Format("(objectCategory={0})",
CategoryType.Computer) Using searcher As New DirectorySearcher(root, filter) Using results = searcher.FindAll() For Each res As SearchResult In results computers.Add(DirectCast( CreateInstance(res.GetDirectoryEntry()), Computer)) Next End Using End Using End Using Return computersEnd Function※root は一般的には New DirectoryEntry(LDAP のルートパス ) をセット※CreateInstance メソッドは DirectoryEntry から DirectoryObject を作
成
![Page 17: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/17.jpg)
17
コンピュータ取得サンプルコード( C# )public static IList<Computer> GetComputers() { var computers = new List<Computer>(); using (var root = GetRootEntry()) { // ルートの DirectoryEntry を取得 var filter = String.Format("(objectCategory={0})",
CategoryType.Computer); using (var searcher = new DirectorySearcher(root, filter)) { using (var results = searcher.FindAll()) { foreach (SearchResult res in results) { groups.Add( (Computer)CreateInstance(res.GetDirectoryEntry())); } } } } return computers;}※root は一般的には new DirectoryEntry(LDAP のルートパス ) をセット※CreateInstance メソッドは DirectoryEntry から DirectoryObject を作
成
![Page 18: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/18.jpg)
18
所属するグループの取得( VB )
Public Function GetBelongGroups(groups As IEnumerable(Of DomainGroup)) As ReadOnlyCollection(Of String)
Dim belongGroups = groups.Where( Function(group) group.Native.IsMember(MyBase.Entry.Path)).Select( Function(group) group.Name).ToList()
belongGroups.Add( DirectoryAccess.GroupTokens.Item(Me.PrimaryGroupId)) belongGroups.Sort() Return belongGroups.AsReadOnly()End Function
ユーザの場合は IADsUser.Groups メソッドで所属するグループを取得できますが、コンピュータの場合はできないのでグループのコレクションが必要です。個々のグループに対してメンバであれば( IADsGroup.IsMember メソッドが True を返せば)そのグループに所属していると判断しています。プライマリ グループの追加についてはユーザの場合と同じです。
![Page 19: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/19.jpg)
19
所属するグループの取得( C# )
Public ReadOnlyCollection<string> GetBelongGroups(IEnumerable<DomainGroup> groups){
var belongGroups = groups.Where( group => group.Native.IsMember(base.Entry.Path)).Select group => group.Name).ToList();
belongGroups.Add( DirectoryAccess.GroupTokens[this.PrimaryGroupId]); belongGroups.Sort(); return belongGroups.AsReadOnly();}
![Page 20: NETからActive Directoryデータにアクセス ~コンピュータ情報の取得と表示~](https://reader036.vdocuments.pub/reader036/viewer/2022082412/5499d3ebac79590e2e8b59a4/html5/thumbnails/20.jpg)
20
詳細や関連情報はブログ等で
.NET から Active Directory にアクセスhttp://www.slideshare.net/mitchin227/active-directory-24695891
ユーザやグループの検索http://blogs.wankuma.com/mitchin/archive/2013/06/26/327958.aspx
SearchResultCollection クラスhttp://blogs.wankuma.com/mitchin/archive/2013/06/30/327977.aspx
ネイティブ ADSI オブジェクトhttp://blogs.wankuma.com/mitchin/archive/2013/07/01/327981.aspx
ユーザの所属するグループの取得http://blogs.wankuma.com/mitchin/archive/2013/07/11/327999.aspx
コンピュータ用のクラスhttp://blogs.wankuma.com/mitchin/archive/2013/11/09/328208.aspxhttp://blogs.wankuma.com/mitchin/archive/2013/11/10/328210.aspx
コンピュータリスト画面http://blogs.wankuma.com/mitchin/archive/2013/11/13/328220.aspx