【问题标题】:Faster way to find out if a user exists on a system?找出系统上是否存在用户的更快方法?
【发布时间】:2009-11-04 18:43:53
【问题描述】:

我有一个应用程序,每次启动时都会检查用户是否存在(如果不创建)。这样做如下:

bool bUserExists = false;
DirectoryEntry dirEntryLocalMachine = 
    new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");

DirectoryEntries dirEntries = dirEntryLocalMachine.Children;

foreach (DirectoryEntry dirEntryUser in dirEntries)
{
    bUserExists = dirEntryUser.Name.Equals("UserName", 
        StringComparison.CurrentCultureIgnoreCase);

    if (bUserExists)
      break;
}

问题出在部署它的大多数系统上。这可能需要 6 - 10 秒,这太长了……我需要找到一种方法来减少这种情况(尽可能)。有没有一种更好更快的方法可以用来验证系统上是否存在用户?

我知道还有其他方法可以解决这个问题,比如让其他应用程序休眠 10 秒,或者让这个工具在准备好时发送消息等等......但是如果我能大大减少它所花费的时间找到用户,这会让我的生活更轻松。

【问题讨论】:

  • 您在机器上寻找本地用户吗?
  • 在应用程序完成启动之前您的用户是否需要存在?
  • 是的,应用程序将检查它是否存在,如果不存在则创建它......工作正常 - 唯一的问题是检查需要很长时间。

标签: c# windows active-directory


【解决方案1】:

.NET 3.5 支持System.DirectoryServices.AccountManagement 命名空间下的新AD 查询类。

要使用它,您需要添加“System.DirectoryServices.AccountManagement”作为参考并添加using 语句。

using System.DirectoryServices.AccountManagement;


using (PrincipalContext pc = new PrincipalContext(ContextType.Machine))
{
    UserPrincipal up = UserPrincipal.FindByIdentity(
        pc,
        IdentityType.SamAccountName,
        "UserName");

    bool UserExists = (up != null);
}

<.net>

对于 3.5 之前的 .NET 版本,这是我在 dotnet-snippets 上找到的一个干净示例

DirectoryEntry dirEntryLocalMachine =
    new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");

bool UserExists =
    dirEntryLocalMachine.Children.Find(userIdentity, "user") != null;

【讨论】:

  • 遗憾的是我不能使用 .NET 3.5,我被 .NET 2.0 卡住了...有没有等价的?
  • 我更新了我的答案以包含一篇关于您正在寻找的内容的精彩文章。它与您当前的方法非常相似,但不是枚举每个对象,而是使用 Children.Find() 函数。请点击链接,因为文章有一个完整的类来处理这个问题,非常好。
  • :( - 太糟糕了,我不知道有没有其他没有提到的解决方案。当然,您可以重新评估是否需要每次调用该逻辑或是否需要被调用启动。也许把它放在一个线程中让用户开始工作?否则,感知起着很大的作用,显示一个指数加速的进度条(即:慢 2 秒,中速 2 秒,那么最后两个超级快)可以创造快速加载的感觉。如果一切都失败了,试试这个:stackoverflow.com/questions/182112/…
【解决方案2】:

您想使用 DirectorySearcher。

类似这样的:

static bool userexists( string strUserName ) {
    string adsPath = string.Format( @"WinNT://{0}", System.Environment.MachineName );
    using( DirectoryEntry de = new DirectoryEntry( adsPath ) ) {
        try {
            return de.Children.Find( strUserName ) != null;
        } catch( Exception e ) {
            return false;
        }
    }
}

那应该更快。此外,如果您所做的只是检查是否存在,则可以减少属性。

【讨论】:

  • 这是一种快速的方法,它适用于 3.5 之前的 .NET 版本(如果这是您的环境)。
  • 我对 DirectoryEntry(活动目录和其他东西)不太熟悉,如果我只有 UserName 可以通过,哪些属性不需要 100% 确定用户不存在?
  • 其实不要包含任何内容,应该没问题。我只是举一个通用的例子,以防你也想知道它们的信息。所以过滤器是你想要的,然后是搜索结果。
  • 搁浅:该代码片段存在一些问题,例如字符串 strDomainName 使用 ds 但 ds 是稍后创建的,并且使用 de which ises strDomainName(循环问题)...
  • 我错了 DirectorySearcher。它仅适用于 AD。我已经更新了在 DirectoryEntry 对象上使用 Find 方法的解决方案。
【解决方案3】:

如果“用户名”存在,则命令提示符中的以下内容返回 1。

净用户 |查找“用户名”/c

【讨论】:

  • 这与找出 C# 中是否存在用户有什么关系?
  • C#可以使用,但恐怕这不是最简洁的解决方案。
  • 我不想开始生成命令 shell 来使用网络用户,用 C# 的东西会更好。
  • @Henri:好的,你可以使用它。您如何在 C# 应用程序中获取结果以查明用户是否存在?请发布代码。
【解决方案4】:

另一种方式如下(支持本地或域用户):

bool UserExists(string userName)
{
    var user = new NTAccount(userName);
    try
    {
        var sid = (SecurityIdentifier)user.Translate(typeof(SecurityIdentifier));
        return true;
    }
    catch (IdentityNotMappedException)
    {
        return false;
    }
}

用户可能不是合格的,也可能是机器/域名合格的 (DOMAIN\UserName)。如果您需要专门检测该帐户是否存在于本地计算机上,请使用Environment.MachineName ($"{Environment.MachineName}\\{userName}") 对其进行限定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2012-03-08
    • 2011-07-30
    相关资源
    最近更新 更多