DirectorySearcher.Asynchronousプロパティをtrueとすると、検索処理が非同期に実行されますが、検索するクライアントプログラム自体は同期的に処理されます。今回はSystem.DirectoryServices.Protocols名前空間のクラスを使用して、検索を非同期に行います。非同期処理は、.NETの非同期パターンと同じ方法(IAsyncResultを使用して非同期結果を受け取る)を使用しますが、紹介する方法では部分検索結果を受け取ることもできるので、.NETの非同期パターン(処理が完全に完了してから呼び出される)とは異なります。
確認環境
- Windows Server 2003 AD環境
- 開発環境:Visual Studio 2008
- .NET 2.0
1. ソリューションの作成
コンソールプロジェクトを作成し、System.DirectoryServices.dllとSystem.DirectoryServices.Protocols.dllをプロジェクトの参照に追加します。
1.1 プログラムの作成
非同期検索を行うプログラムを掲載します。GetLdapConnection()をKerberos認証を使用して現在実行中のユーザでLDAPに接続する処理です。別のユーザの資格情報を利用する場合はコメントされているCredentialに資格情報を設定します。
サンプルでは、AsyncCallbackとAsyncCallback2というコールバックメソッドを使用して非同期検索のコールバックを受け取るようにしています。AsyncCallback2の場合は、非同期部分検索結果も受け取るように実装されています。非同期検索結果のみを受けとるAsyncCallbackを使用する場合は、コメントにされている_connect.BeginSendRequestの箇所のコメントを解除し、コールバックにAsyncCallback2を指定しているステートメントをコメントにします。非同期検索中に部分検索をコールバックメソッドから受け取れるようにするかはLdapConnection.BeginSendRequestを呼び出し時に指定するPartialResultProcessingに適切な値を指定します。
/// <summary> /// System.DirectoryServices.Protocols名前空間のクラスを使用 /// して非同期検索を実施する。.NETの非同期実行パターンと異なり、 /// 全検索結果を待機せず、検索結果の一部を取得できる。 /// System.DirectoryServices.Protocols.dllを参照に追加 /// </summary> class Program { static LdapConnection _connect; static void Main(string[] args) { _connect = GetLdapConnection(); _connect.Bind(); SearchRequest request = new SearchRequest("DC=crm1,DC=local", "(objectClass=user)", SearchScope.Subtree, null); request.SizeLimit = 255; // 非同期検索のみ行う場合 //IAsyncResult result = _connect.BeginSendRequest(request // , PartialResultProcessing.NoPartialResultSupport, new AsyncCallback(AsyncCallback), null); // 非同期検索を行い、部分検索結果を受け取る場合 IAsyncResult result = _connect.BeginSendRequest(request, PartialResultProcessing.ReturnPartialResultsAndNotifyCallback, new AsyncCallback(AsyncCallback2), null); result.AsyncWaitHandle.WaitOne(); Console.WriteLine("メインスレッド終了.検索完了後Enterクリック"); Console.ReadLine(); } static LdapConnection GetLdapConnection() { LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier("crm1.local:389")); //con.Credential = new NetworkCredential("Administrator", "password", "crm1"); // ADのKerberos認証を使用する場合 con.SessionOptions.Sealing = true; // SSLを使用する場合 //con.SessionOptions.SecureSocketLayer = true; return con; } static void AsyncCallback(IAsyncResult result) { Console.WriteLine("検索完了"); SearchResponse response = _connect.EndSendRequest(result) as SearchResponse; foreach (SearchResultEntry entry in response.Entries) { Console.WriteLine(entry.DistinguishedName); } } static void AsyncCallback2(IAsyncResult result) { Console.WriteLine("コールバックスレッド"); if (!result.IsCompleted) { PartialResultsCollection partialResultCollection = _connect.GetPartialResults(result); Console.WriteLine("部分検索結果"); for (int i = 0; i < partialResultCollection.Count; ++i) { SearchResultEntry entry = partialResultCollection[i] as SearchResultEntry; if (entry != null) { Console.WriteLine(entry.DistinguishedName); } } } else { Console.WriteLine("検索完了"); SearchResponse response = _connect.EndSendRequest(result) as SearchResponse; foreach (SearchResultEntry entry in response.Entries) { Console.WriteLine(entry.DistinguishedName); } } } }
2.おわりに
説明は以上です。SDS.Pを使用すると、非同期検索を行え、部分検索結果を受け取ることもできます。
間違い、指摘点がありましたらご連絡ください。
さんのコメント: さんのコメント: