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を使用すると、非同期検索を行え、部分検索結果を受け取ることもできます。
間違い、指摘点がありましたらご連絡ください。