2017-10-13 1 views
2

私はActive Directoryを照会するために使用するいくつかのコードを最適化しています。メソッドの1つは、ディレクトリエントリのuSNCreatedプロパティによって特定される特定の更新以降に変更されたすべてのADユーザーを取得します。基本的にそれがのC#の同等のものをやっている:、__ComObjectからInvokableメソッドを取得

public IEnumerable<UserPrincipal> GetUpdatedUsers(string samAccountName, long lastUsnChanged) 
{ 
    using (var context = new PrincipalContext(ContextType.Domain)) 
    using (var userSearcher = new PrincipalSearcher(new UserPrincipal(context))) 
    { 
     var items = userSearcher.FindAll().Cast<UserPrincipal>(); 
     return items.Where(x => GetUsnChanged(x) > lastUsnChanged).ToArray(); 
    } 
} 

private static long GetUsnChanged(Principal item) 
{ 
    var de = item.GetUnderlyingObject() as DirectoryEntry; 
    if (de == null) 
     return 0; 

    if (!de.Properties.Contains("uSNCreated")) 
     return 0; 

    var usn = de.Properties["uSNCreated"].Value; 
    var t = usn.GetType(); 

    var highPart = (int)t.InvokeMember("HighPart", BindingFlags.GetProperty, null, usn, null); 
    var lowPart = (int)t.InvokeMember("LowPart", BindingFlags.GetProperty, null, usn, null); 

    return highPart * ((long)uint.MaxValue + 1) + lowPart; 
} 

さて、このコードが作業を行います。

uSNCreated> someValueの

コードは(多かれ少なかれ)であるPrincipalSearcherから選択* InvokeMember()への繰り返し呼び出しは遅いです。私がしたいのは、HighPartとLowPartプロパティへの参照を取得して、InvokeMember()を呼び出すたびにそれらを「再発見」する必要のないオーバーヘッドを何度も繰り返して呼び出すことができるようにすることです。

私はしかし、私は常にnullを返します()

static PropertyInfo highProp = highProp 
    ?? t.GetProperty("HighPart", BindingFlags.GetProperty); 
highPart = (int)highProp.GetValue(usn); 

Unfortnately t.GetPropertyの線に沿って何かを行うことができだろうと。 GetProperties()、GetMethods()、およびGetMembers()によって返された結果を見ると、BindingFlags.NonPublicを使用していても、表示できる「HighPart」または「LowPart」は表示されません。 (私はInvokeMember()を使用して呼び出すことができます)

これを解決する方法はありますか、それとも敗北を認める時間はありますか?

+1

[インターフェイス宣言](https://referencesource.microsoft.com/#System.Web/Security/ADMembershipProvider.cs,96419c0a980e9d0e)をコピーして貼り付けることができます。または、c:\ windows \ system32 \ activeds.tlbへの参照を追加します。 Valueプロパティの戻り値をこのインターフェイスにキャストします。これが実際に高速であるという見通しはそれほど高くないので、ドメインコントローラへのネットワークラウンドトリップのコストを見ているだけです。 –

+0

あなたは、これがパフォーマンスのために何もしていないようですが、確かにコードを読みやすくしています。それは私の本で+1価値がある - ありがとう! – Pete

答えて

2

System.DirectoryServices.AccountManagement名前空間のクラスは、単純なケースで使用するように設計されています。 g。ユーザーまたはグループを見つける必要があります。これらのクラスには既知のパフォーマンス問題があります。 DirectorySearcherまたはLdapConnection/SearchRequestを使用することをお勧めします。この場合、クライアントではなくサーバー上のオブジェクトをフィルタリングすることができます。これにより、パフォーマンスが大幅に向上し、ネットワーク経由で送信されるデータが削減されます。次に、DirectorySearcherを使用してすべてのユーザーを検索する例を示します。Get all users from AD domain フィルタは(&(objectClass = user)(uSNCreated> = x + 1))のようになります。ここでxは最後のusnです。 usnCreated属性でオブジェクトを追跡すると、最後のusnから作成されたユーザーのみが取得されることに注意してください。変更を追跡するには、usnChanged属性を使用します。

+0

uSNCreatedとuSNChangedの通話が良好です。私はDirectorySeacherを使用しようとしましたが、 "&(&(objectClass = user)(uSNChanged> 132440887)))検索フィルタが無効です。私はこれでプラグインし続けます - 私は多くの場合、結果のサーバー側のフィルタリングの考え方を好む – Pete

+0

>を>で置き換えて、最後にusnを1つ増やします。 – oldovets

+0

私は絶対にうんざりです! DirectorySearcherは>演算子を処理できません???それは素晴らしいですが、あなたは正しいです。これは魅力のように機能します - ありがとう! – Pete

関連する問題