Определить текущий контроллер домена программно

Мне нужно запросить текущий контроллер домена, возможно, основной, чтобы изменить пароль пользователя.

(P)Имя DC должно быть полным, т.е. DC=pdc,DC=example,DC=com (как правильно назвать такое обозначение?)

Как это можно сделать с помощью C#?


person abatishchev    schedule 25.10.2010    source источник


Ответы (4)


Чтобы получить информацию, когда DomainController существует в домене, к которому не принадлежит ваша машина, вам нужно нечто большее.

  DirectoryContext domainContext =  new DirectoryContext(DirectoryContextType.Domain, "targetDomainName", "validUserInDomain", "validUserPassword");

  var domain = System.DirectoryServices.ActiveDirectory.Domain.GetDomain(domainContext);
  var controller = domain.FindDomainController();
person Brett Veenstra    schedule 13.11.2012
comment
Я не хочу передавать имя пользователя и пароль. - person abatishchev; 13.11.2012
comment
К сожалению, если вы пересекаете домены, вам необходимо. В противном случае ваша существующая личность не будет распознана. Даже с новым пространством имен 3.5 System.DirectoryServices.AccountManagement вам нужно будет указать действительное имя пользователя/пароль в внешнем домене. - person Brett Veenstra; 15.11.2012
comment
Это не работает, потому что ваш локальный компьютер не сможет найти контроллер домена для этого домена. - person Bluebaron; 30.01.2016

Мы используем нечто подобное для наших внутренних приложений.

Должно вернуть что-то вроде DC=d,DC=r,DC=ABC,DC=com

public static string RetrieveRootDseDefaultNamingContext()
{
    String RootDsePath = "LDAP://RootDSE";
    const string DefaultNamingContextPropertyName = "defaultNamingContext";

    DirectoryEntry rootDse = new DirectoryEntry(RootDsePath)
    {
        AuthenticationType = AuthenticationTypes.Secure;
    };
    object propertyValue = rootDse.Properties[DefaultNamingContextPropertyName].Value;

    return propertyValue != null ? propertyValue.ToString() : null;
}
person Lareau    schedule 25.10.2010
comment
Да, ты прав. Обычно у нас есть некоторый пользовательский код ведения журнала в операторе catch, но я убрал его для этого примера. - person Lareau; 26.10.2010
comment
@abatishchev: это утверждение неверно - вызов только throw сохранит трассировку стека; создание нового исключения или выполнение throw ex; приведет к поломке стека вызовов; см.: weblogs.asp.net/fmarguerie/archive/2008/01/02/ - person marc_s; 05.11.2010
comment
@marc_s: да, ты прав, я ошибался (во фразе о трассировке стека). в любом случае это не имеет смысла до регистрации и т. д., как сказал @Lareau - person abatishchev; 05.11.2010

(требуется System.DirectoryServices.AccountManagement.dll):

using (var context = new System.DirectoryServices.AccountManagement.PrincipalContext(ContextType.Domain))
{
    string server = context.ConnectedServer; // "pdc.examle.com"
    string[] splitted = server.Split('.'); // { "pdc", "example", "com" }
    IEnumerable<string> formatted = splitted.Select(s => String.Format("DC={0}", s));// { "DC=pdc", "DC=example", "DC=com" }
    string joined = String.Join(",", formatted); // "DC=pdc,DC=example,DC=com"

    // or just in one string

    string pdc = String.Join(",", context.ConnectedServer.Split('.').Select(s => String.Format("DC={0}", s)));
}
person abatishchev    schedule 25.10.2010
comment
Это не сработает в междоменной ситуации (например, ваш компьютер не является частью домена, в котором существует контроллер домена). Смотрите мой ответ для такого решения. - person Brett Veenstra; 13.11.2012

Если вы хотите взаимодействовать с Active Directory, вам не нужно знать, где находится FSMO роли по большей части. Если вы хотите изменить топологию AD в своей программе (я бы этого не сделал), посмотрите Контроллер домена.

Если вы хотите изменить пароль пользователя, вы можете вызвать эти действия для объекта «Пользователь», и Active Directory позаботится о том, чтобы изменения были правильно воспроизведены.

скопировано с http://www.rootsilver.com/2007/08/how-to-change-a-user-password

public static void ChangePassword(string userName, string oldPassword, string newPassword)
{
        string path = "LDAP://CN=" + userName + ",CN=Users,DC=demo,DC=domain,DC=com";

        //Instantiate a new DirectoryEntry using an administrator uid/pwd
        //In real life, you'd store the admin uid/pwd  elsewhere
        DirectoryEntry directoryEntry = new DirectoryEntry(path, "administrator", "password");

        try
        {
           directoryEntry.Invoke("ChangePassword", new object[]{oldPassword, newPassword});
        }
        catch (Exception ex)  //TODO: catch a specific exception ! :)
        {
           Console.WriteLine(ex.Message);
        }

        Console.WriteLine("success");
}
person jwmiller5    schedule 25.10.2010
comment
Как вы думаете, могу ли я изменить свой текущий пароль, используя собственное имя пользователя и текущий пароль? - person abatishchev; 05.11.2010