从__ComObject获取Invokable方法

时间:2017-10-13 18:30:38

标签: c# active-directory invoke comobject

我正在优化我们用于查询Active Directory的一些代码。其中一种方法获取自特定更新以来已更改的所有AD用户,这些用户由目录条目的uSNCreated属性确定。基本上它正在做C#等价物:

  

从PrincipalSearcher中选择*,其中uSNCreated> someValue中

代码是(或多或少):

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;
}

现在这段代码可以正常工作,但是对InvokeMember()的重复调用是缓慢的。我想要做的是获取对HighPart和LowPart属性的引用,以便我可以反复调用它们,而不必每次调用InvokeMember()时都需要“重新发现”它们。

我想我可以按照

的方式做点什么
static PropertyInfo highProp = highProp
    ?? t.GetProperty("HighPart", BindingFlags.GetProperty);
highPart = (int)highProp.GetValue(usn);

不幸地,t.GetProperty()总是返回null。查看GetProperties(),GetMethods()和GetMembers()返回的结果,似乎没有可见的“HighPart”或“LowPart”,即使使用BindingFlags.NonPublic - 只需__ComObject似乎没有暴露他们(即使我可以调用使用InvokeMember())

有没有办法解决这个问题,或者是时候承认失败了?

1 个答案:

答案 0 :(得分:2)

System.DirectoryServices.AccountManagement命名空间中的类设计用于简单情况,例如: G。你需要找到一个用户或组。这些类已知性能问题。我建议使用DirectorySearcher或LdapConnection / SearchRequest。在这种情况下,您可以过滤服务器上的对象,而不是客户端上的对象,这将显着提高性能并减少通过网络发送的数据。以下是使用DirectorySearcher查找所有用户的示例:Get all users from AD domain 在你的情况下,过滤器看起来像(&amp;(objectClass = user)(uSNCreated&gt; = x + 1))其中x是你的最后一个usn。 请注意,如果使用usnCreated属性跟踪对象,则只会获得自上次使用以来创建的用户。要跟踪更改,请使用usnChanged属性