2010-10-25 104 views
6

我需要查詢當前域控制器,可能主要更改用戶密碼。以編程方式確定當前域控制器

(P),DC名稱應該是完全合格的,即DC=pdc,DC=example,DC=com(如何正確名稱,符號?)

如何可以在使用C#來完成?

回答

1

(需要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))); 
} 
+0

這不適用於跨域情況(例如,您的計算機不是域控制器所在的域的一部分)。看到我的答案這樣的解決方案。 – 2012-11-13 14:44:26

+0

@Firo:謝謝,修正。錯誤是通過'string []' - >'IEnumerable ' – abatishchev 2012-11-30 07:34:26

0

如果您正在尋找交互的Active Directory,您不應該知道在哪裏FSMO角色大部分。如果你想從程序中更改AD拓撲(我不會),請看DomainController類。

如果要更改用戶密碼,可以在用戶對象上調用這些操作,並且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"); 
} 
+0

修復的。您如何看待我可以使用我自己的用戶名和當前密碼更改當前密碼? – abatishchev 2010-11-05 10:33:02

2

複製我們使用這樣的事情對我們的內部應用程序。

應該返回類似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; 
} 
+0

是的,你是對的。我們通常在catch語句中有一些自定義日誌記錄代碼,但是我爲此示例拿出了它。 – Lareau 2010-10-26 14:31:20

+1

@abatishchev:該語句是錯誤的 - 只調用'throw'將**保存**堆棧跟蹤;創建一個新的異常或者執行'throw ex;'會破壞調用堆棧;見:http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx – 2010-11-05 10:16:44

+0

@marc_s:是啊,你對,我錯了(在關於堆棧跟蹤的短語中)。無論如何這是沒有意義的,直到日誌等@Lareau說 – abatishchev 2010-11-05 10:24:31

5

檢索信息時存在域中的DomainController在你的機器不屬於,你需要更多的東西。

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

    var domain = System.DirectoryServices.ActiveDirectory.Domain.GetDomain(domainContext); 
    var controller = domain.FindDomainController(); 
+0

我不想傳遞用戶名和密碼。 – abatishchev 2012-11-13 19:43:15

+0

不幸的是,如果你跨域,你需要。否則您的現有身份將不會被識別。即使使用「新」3.5「System.DirectoryServices.AccountManagement」命名空間,您也必須在* external *域中包含有效的用戶名/密碼。 – 2012-11-14 20:21:15

+0

這不起作用,因爲您的本地計算機將無法找到該域的DC。 – Bluebaron 2016-01-29 23:26:28

相關問題