.Net平台操作活动目录Active Directory,使用System.DirectoryServices.ActiveDirectory,主要是User OU 和Group的操作。
代码运行了一年多,还没有出现问题,应该算是经过了验证。
更新的代码在www.codeplex.com/ADBlock
/* * Copyright [2008]. Sherwin Zhu. sherwinzhu@126.com * * http://www.gnu.org/licenses/lgpl-3.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Text; using System.DirectoryServices; using System.Collections; using System.DirectoryServices.ActiveDirectory; namespace TB.ADBlock { /// <summary> /// 用于进行AD管理里的对象,提供操作AD的静态方法。 /// </summary> /// <remarks> /// 这里ADsPath可以是LDAP://DN和LDAP://<GUID>两种形式,但不限于这种形式。 /// 一般方法均提供2种形式,一种是用参数提供的用户身份标识,一种是用默认的用户身份标识。 /// 默认用户身份标识取决于当前进程的用户身份标识。 /// </remarks> public class ADManager { #region 域信息 /// <summary> /// 将友好的域名称(friendly domain name)转换为合格的域名称(fully qualified domain name)。 /// eg:tb -- > tb.com /// </summary> /// <param name="friendlyDomainName">友好的域名称(friendly domain name)。 /// 可以是: /// 域控制器的 DNS 名称。 /// ADAM 服务器的 DNS 名称和 LDAP 端口号(如 adam_instance.fabrikam.com:389)。 /// 域的 DNS 名称,如 sales.corp.fabrikam.com。 /// 林的 DNS 名称,如 corp.fabrikam.com。 /// 应用程序分区的 DNS 名称。 /// 与服务连接点关联的关键字之一,该服务连接点由配置集的 ADAM 实例注册。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public static string FriendlyDomainToLdapDomain(string friendlyDomainName, string userName, string password) { string ldapPath = null; try { DirectoryContext objContext = null; if (UseDefaultIdentity(userName, password)) objContext = new DirectoryContext(DirectoryContextType.Domain, friendlyDomainName); else objContext = new DirectoryContext(DirectoryContextType.Domain, friendlyDomainName, userName, password); ldapPath = System.DirectoryServices.ActiveDirectory.Domain.GetDomain(objContext).Name; } catch (DirectoryServicesCOMException dsce) { throw dsce; } return ldapPath; } /// <summary> /// 将友好的域名称(friendly domain name)转换为合格的域名称(fully qualified domain name)。 /// eg:tb -- > tb.com /// </summary> /// <param name="friendlyDomainName">友好的域名称(friendly domain name)。 /// 可以是: /// 域控制器的 DNS 名称。 /// ADAM 服务器的 DNS 名称和 LDAP 端口号(如 adam_instance.fabrikam.com:389)。 /// 域的 DNS 名称,如 sales.corp.fabrikam.com。 /// 林的 DNS 名称,如 corp.fabrikam.com。 /// 应用程序分区的 DNS 名称。 /// 与服务连接点关联的关键字之一,该服务连接点由配置集的 ADAM 实例注册。</param> /// <returns></returns> public static string FriendlyDomainToLdapDomain(string friendlyDomainName) { return FriendlyDomainToLdapDomain(friendlyDomainName, null, null); } /// <summary> /// 获取当前用户上下文的 Forest 对象中的所有域名称。 /// </summary> /// <returns></returns> public static List<string> EnumerateDomains() { List<string> alDomains = new List<string>(); Forest currentForest = Forest.GetCurrentForest(); DomainCollection myDomains = currentForest.Domains; foreach (System.DirectoryServices.ActiveDirectory.Domain objDomain in myDomains) { alDomains.Add(objDomain.Name); } return alDomains; } /// <summary> /// 获取当前用户上下文的 Forest 对象中所有的全局目录。 /// </summary> /// <returns></returns> public static List<string> EnumerateGlobalCatalogs() { List<string> alGCs = new List<string>(); Forest currentForest = Forest.GetCurrentForest(); foreach (GlobalCatalog gc in currentForest.GlobalCatalogs) { alGCs.Add(gc.Name); } return alGCs; } /// <summary> /// 获取当前用户身份标识的 Domain 对象中的域控制器。 /// </summary> /// <returns></returns> public static List<string> EnumerateDomainControllers() { List<string> alDcs = new List<string>(); System.DirectoryServices.ActiveDirectory.Domain domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain(); foreach (DomainController dc in domain.DomainControllers) { alDcs.Add(dc.Name); } return alDcs; } #endregion #region Common /// <summary> /// 检验指定的DirectoryEntry是否存在 /// </summary> /// <param name="path">ADsPath,自动添加LDAP_IDENTITY。完全转义过的。</param> /// <returns></returns> public static bool Exists(string path) { if (path.StartsWith(ParaMgr.LDAP_IDENTITY)) return DirectoryEntry.Exists(path); else return DirectoryEntry.Exists(ParaMgr.LDAP_IDENTITY + path); } /// <summary> /// 移动DirectoryEntry到指定位置。 /// </summary> /// <param name="objectPath">要移动的DirectoryEntry的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <remarks>被移动的对象和要移动到的位置对象必须使用DN形式的路径创建,不能使用GUID形式的路径,否则会引发异常。</remarks> public static void Move(string objectPath, string newLocationPath, string userName, string password) { if (!Exists(objectPath)) throw new EntryNotExistException("需要被移动的对象不存在。"); DirectoryEntry de = null; try { de = GetByPath(objectPath, userName, password); Move(de, newLocationPath, userName, password); } catch { throw; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 移动DirectoryEntry到指定位置,使用默认用户身份标识。 /// </summary> /// <param name="objectPath">要移动的DirectoryEntry的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式。完全转义过的。</param> public static void Move(string objectPath, string newLocationPath) { Move(objectPath, newLocationPath, null, null); } /// <summary> /// 移动DirectoryEntry到指定位置。 /// </summary> /// <param name="de">要移动的DirectoryEntry对象</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <remarks>被移动的对象和要移动到的位置对象必须使用DN形式的路径创建,不能使用GUID形式的路径,否则会引发异常。</remarks> internal static void Move(DirectoryEntry de, string newLocationPath, string userName, string password) { if (!Exists(newLocationPath)) throw new EntryNotExistException("移动到的位置对象不存在。"); DirectoryEntry newLocation = null; try { newLocation = GetByPath(newLocationPath, userName, password); string newLocationDN = Utils.EscapeDNBackslashedChar(newLocation.Properties[BaseObject.PROPERTY_DN].Value.ToString()); string deDN = Utils.EscapeDNBackslashedChar(de.Properties[BaseObject.PROPERTY_DN].Value.ToString()); if (Exists(Utils.GenerateDN(Utils.GetRDN(deDN), deDN))) throw new SameRDNException("移动到的位置下存在同名对象。"); de.MoveTo(newLocation); de.CommitChanges(); } catch (InvalidOperationException ioe) // 指定的 DirectoryEntry 不是容器。 { throw new NotContainerException(ioe.Message, ioe); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (newLocation != null) { newLocation.Close(); newLocation.Dispose(); } } } /// <summary> /// 获取应用程序设置的默认域。 /// </summary> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public static DirectoryEntry GetAppSetDomain(string userName, string password) { return GetByDN(ParaMgr.ADFullPath, userName, password); } /// <summary> /// 获取应用程序设置的默认域,使用默认用户身份标识。 /// </summary> /// <returns></returns> public static DirectoryEntry GetAppSetDomain() { return GetAppSetDomain(null, null); } // 根据用户名和密码,判断是否应该使用默认用户身份标识。 private static bool UseDefaultIdentity(string userName, string password) { if (String.IsNullOrEmpty(userName)) return true; else return false; } #endregion #region Get & Search /// <summary> /// 获取DirectoryEntry /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootDN">根对象DN,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry Get(string schema, string objectClass, string objectCategory, string rootDN, string userName, string password) { DirectoryEntry de = GetByDN((String.IsNullOrEmpty(rootDN) ? (ParaMgr.ADFullPath) : rootDN), userName, password); DirectorySearcher deSearch = new DirectorySearcher(); deSearch.SearchRoot = de; if (!String.IsNullOrEmpty(objectClass) || !String.IsNullOrEmpty(objectCategory) || !String.IsNullOrEmpty(schema)) { deSearch.Filter = String.Format("(&{0}{1}{2})", ((!String.IsNullOrEmpty(objectClass)) ? String.Format("(objectClass={0})", objectClass) : ""), ((!String.IsNullOrEmpty(objectCategory)) ? String.Format("(objectCategory={0})", objectCategory) : ""), ((!String.IsNullOrEmpty(schema)) ? String.Format("({0})", schema) : "") ); } deSearch.SearchScope = SearchScope.Subtree; SearchResult results = deSearch.FindOne(); DirectoryEntry rde = null; if (results != null) rde = GetByPath(results.Path); else rde = null; de.Close(); de.Dispose(); return rde; } /// <summary> /// 获取DirectoryEntry,使用默认用户身份标识。 /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootDN">根对象DN,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry Get(string schema, string objectClass, string objectCategory, string rootDN) { return Get(schema, objectClass, objectCategory, rootDN, null, null); } /// <summary> /// 查找DirectoryEntry /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootPath">根对象ADsPath</param> /// <param name="scope">SearchScope</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回空集合。</returns> internal static List<DirectoryEntry> Search(string schema, string objectClass, string objectCategory, string rootPath, SearchScope scope, string userName, string password) { DirectoryEntry de = null; if (!String.IsNullOrEmpty(rootPath)) { de = GetByPath(rootPath, userName, password); } if (de == null) de = GetByPath(ParaMgr.ADFullPath, userName, password); DirectorySearcher deSearch = new DirectorySearcher(); if (de != null) deSearch.SearchRoot = de; if (!String.IsNullOrEmpty(objectClass) || !String.IsNullOrEmpty(objectCategory) || !String.IsNullOrEmpty(schema)) { deSearch.Filter = String.Format("(&{0}{1}{2})", ((!String.IsNullOrEmpty(objectClass)) ? String.Format("(objectClass={0})", objectClass) : ""), ((!String.IsNullOrEmpty(objectCategory)) ? String.Format("(objectCategory={0})", objectCategory) : ""), ((!String.IsNullOrEmpty(schema)) ? String.Format("({0})", schema) : "") ); } deSearch.SearchScope = scope; SearchResultCollection results = deSearch.FindAll(); List<DirectoryEntry> entries = new List<DirectoryEntry>(); if (results != null) { foreach (SearchResult se in results) { //entries.Add(GetByPath(se.Path)); entries.Add(se.GetDirectoryEntry()); } } de.Close(); de.Dispose(); return entries; } /// <summary> /// 查找DirectoryEntry,使用默认用户身份标识。 /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootPath">根对象ADsPath</param> /// <param name="scope">SearchScope</param> /// <returns>如果不存在,返回空集合。</returns> internal static List<DirectoryEntry> Search(string schema, string objectClass, string objectCategory, string rootPath, SearchScope scope) { return Search(schema, objectClass, objectCategory, rootPath, scope, null, null); } /// <summary> /// 查找DirectoryEntry,结果为字符串形式 /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootPath">根对象ADsPath</param> /// <param name="scope">SearchScope</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回空集合。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass。 /// 最后添加了sAMAccountName。</remarks> internal static List<string[]> Search2(string schema, string objectClass, string objectCategory, string rootPath, SearchScope scope, string userName, string password) { DirectoryEntry de = null; if (!String.IsNullOrEmpty(rootPath)) { de = GetByPath(rootPath, userName, password); } if (de == null) de = GetByPath(ParaMgr.ADFullPath, userName, password); DirectorySearcher deSearch = new DirectorySearcher(); if (de != null) deSearch.SearchRoot = de; if (!String.IsNullOrEmpty(objectClass) || !String.IsNullOrEmpty(objectCategory) || !String.IsNullOrEmpty(schema)) { deSearch.Filter = String.Format("(&{0}{1}{2})", ((!String.IsNullOrEmpty(objectClass)) ? String.Format("(objectClass={0})", objectClass) : ""), ((!String.IsNullOrEmpty(objectCategory)) ? String.Format("(objectCategory={0})", objectCategory) : ""), ((!String.IsNullOrEmpty(schema)) ? String.Format("({0})", schema) : "") ); } deSearch.SearchScope = scope; SearchResultCollection results = deSearch.FindAll(); List<string[]> entriesProperty = new List<string[]>(); if (results != null) { foreach (SearchResult se in results) { string nativeGuid = ""; foreach(byte g in (byte[])se.Properties["objectguid"][0]) { nativeGuid += g.ToString("x2"); } string oc = ""; foreach (object c in se.Properties["objectclass"]) { oc = oc + "," + c.ToString(); } string sAMAccountName = null; if (se.Properties.Contains("sAMAccountName")) sAMAccountName = se.Properties["sAMAccountName"][0].ToString(); entriesProperty.Add(new string[] { se.Properties["distinguishedname"][0].ToString(), Utils.ConvertNativeGuidToGuid(nativeGuid).ToString(), se.Properties["name"][0].ToString(), ((se.Properties["description"].Count > 0) ? se.Properties["description"][0].ToString() : null), se.Properties["adspath"][0].ToString(), se.Properties["objectcategory"][0].ToString(), oc.Substring(1), sAMAccountName }); } } de.Close(); de.Dispose(); return entriesProperty; } /// <summary> /// 查找DirectoryEntry,使用默认用户身份标识。结果为字符串形式 /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootPath">根对象ADsPath</param> /// <param name="scope">SearchScope</param> /// <returns>如果不存在,返回空集合。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass</remarks> internal static List<string[]> Search2(string schema, string objectClass, string objectCategory, string rootPath, SearchScope scope) { return Search2(schema, objectClass, objectCategory, rootPath, scope, null, null); } /// <summary> /// 查找DirectoryEntry /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootPath">根对象ADsPath</param> /// <param name="scope">SearchScope</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回空集合。</returns> internal static SearchResultCollection Search3(string schema, string objectClass, string objectCategory, string rootPath, SearchScope scope, string userName, string password) { DirectoryEntry de = null; if (!String.IsNullOrEmpty(rootPath)) { de = GetByPath(rootPath, userName, password); } if (de == null) de = GetByPath(ParaMgr.ADFullPath, userName, password); DirectorySearcher deSearch = new DirectorySearcher(); if (de != null) deSearch.SearchRoot = de; if (!String.IsNullOrEmpty(objectClass) || !String.IsNullOrEmpty(objectCategory) || !String.IsNullOrEmpty(schema)) { deSearch.Filter = String.Format("(&{0}{1}{2})", ((!String.IsNullOrEmpty(objectClass)) ? String.Format("(objectClass={0})", objectClass) : ""), ((!String.IsNullOrEmpty(objectCategory)) ? String.Format("(objectCategory={0})", objectCategory) : ""), ((!String.IsNullOrEmpty(schema)) ? String.Format("({0})", schema) : "") ); } deSearch.SearchScope = scope; SearchResultCollection results = deSearch.FindAll(); de.Close(); de.Dispose(); return results; } /// <summary> /// 查找DirectoryEntry,使用默认用户身份标识。 /// </summary> /// <param name="schema">自定义模式</param> /// <param name="objectClass">类型</param> /// <param name="objectCategory">类别</param> /// <param name="rootPath">根对象ADsPath</param> /// <param name="scope">SearchScope</param> /// <returns>如果不存在,返回空集合。</returns> internal static SearchResultCollection Search3(string schema, string objectClass, string objectCategory, string rootPath, SearchScope scope) { return Search3(schema, objectClass, objectCategory, rootPath, scope, null, null); } /// <summary> /// 根据DirectoryEntry的Guid得到DirectoryEntry对象。 /// </summary> /// <param name="guid">Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry GetByGuid(Guid guid, string userName, string password) { return GetByPath(Utils.GenerateADsPath(guid), userName, password); } /// <summary> /// 根据DirectoryEntry的Guid得到DirectoryEntry对象,使用默认用户身份标识。 /// </summary> /// <param name="guid">Guid</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry GetByGuid(Guid guid) { return GetByGuid(guid, null,null ); } /// <summary> /// 根据DirectoryEntry的SID得到DirectoryEntry对象。 /// </summary> /// <param name="sid">objectSID</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry GetBySid(string sid, string userName, string password) { return Get("objectSID=" + sid, null, null, null, userName, password); } /// <summary> /// 根据DirectoryEntry的SID得到DirectoryEntry对象,使用默认用户身份标识。 /// </summary> /// <param name="sid">objectSID</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry GetBySid(string sid) { return GetBySid(sid, null, null); } /// <summary> /// 根据DirectoryEntry的DN得到DirectoryEntry对象。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry GetByDN(string dn, string userName, string password) { return GetByPath(ParaMgr.LDAP_IDENTITY + dn, userName, password); } /// <summary> /// 根据DirectoryEntry的DN得到DirectoryEntry对象,使用默认用户身份标识。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> internal static DirectoryEntry GetByDN(string dn) { return GetByDN(dn, null, null); } /// <summary> /// 根据DirectoryEntry的ADsPath得到DirectoryEntry对象。 /// </summary> /// <param name="path">完整的ADsPath,自动添加LDAP_IDENTITY。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> /// <returns></returns> internal static DirectoryEntry GetByPath(string path, string userName, string password) { if (Exists(path)) { if (UseDefaultIdentity(userName, password)) return new DirectoryEntry((path.StartsWith(ParaMgr.LDAP_IDENTITY)) ? path : (ParaMgr.LDAP_IDENTITY + path)); else return new DirectoryEntry( (path.StartsWith(ParaMgr.LDAP_IDENTITY)) ? path : (ParaMgr.LDAP_IDENTITY + path), userName, password, AuthenticationTypes.Secure); } else return null; } /// <summary> /// 根据DirectoryEntry的ADsPath得到DirectoryEntry对象,使用默认用户身份标识。 /// </summary> /// <param name="path">完整的ADsPath。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> /// <returns></returns> internal static DirectoryEntry GetByPath(string path) { return GetByPath(path, null, null); } #endregion #region User #region Search /// <summary> /// 获取指定所有用户。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static List<User> GetUserAll(string rootPath, string userName, string password) { List<DirectoryEntry> entries = Search(null, "user", "person", rootPath, SearchScope.Subtree, userName, password); List<User> users = new List<User>(); foreach (DirectoryEntry de in entries) { users.Add(new User(de)); de.Close(); de.Dispose(); } return users; } /// <summary> /// 获取指定所有用户,使用默认用户身份标识。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> public static List<User> GetUserAll(string rootPath) { return GetUserAll(rootPath, null, null); } /// <summary> /// 获取指定所有用户。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass。 /// 最后添加了sAMAccountName。</remarks> public static List<string[]> GetUserAllSimple(string rootPath, string userName, string password) { return Search2(null, "user", "person", rootPath, SearchScope.Subtree, userName, password); } /// <summary> /// 获取指定所有用户,使用默认用户身份标识。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass</remarks> public static List<string[]> GetUserAllSimple(string rootPath) { return GetUserAllSimple(rootPath, null, null); } /// <summary> /// 获取指定所有用户。直接解析查询结果,速度较GetUserAll快。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static List<User> GetUserAllQuick(string rootPath, string userName, string password) { SearchResultCollection results = Search3(null, "user", "person", rootPath, SearchScope.Subtree, userName, password); List<User> users = new List<User>(); foreach (SearchResult se in results) { users.Add(new User(se)); } return users; } /// <summary> /// 获取指定所有用户,使用默认用户身份标识。直接解析查询结果,速度较GetUserAll快。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> public static List<User> GetUserAllQuick(string rootPath) { return GetUserAllQuick(rootPath, null, null); } /// <summary> /// 根据userPrincipalName获取Group。 /// </summary> /// <param name="userPrincipalName">userPrincipalName。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByPrincipalName(string userPrincipalName, string userName, string password) { List<DirectoryEntry> entries = Search("userPrincipalName=" + Utils.Escape4Query(userPrincipalName), "user", "person", null, SearchScope.Subtree, userName, password); if (entries.Count == 1) { DirectoryEntry de = entries[0]; User user = new User(de); de.Close(); de.Dispose(); return user; } return null; } /// <summary> /// 根据sAMAccountName获取User。 /// </summary> /// <param name="sAMAccountName">sAMAccountName。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserBySAMAccountName(string sAMAccountName, string userName, string password) { List<DirectoryEntry> entries = Search("sAMAccountName=" + Utils.Escape4Query(sAMAccountName), "user", "person", null, SearchScope.Subtree, userName, password); if (entries.Count == 1) { DirectoryEntry de = entries[0]; User user = new User(de); de.Close(); de.Dispose(); return user; } return null; } #endregion #region Get /// <summary> /// 根据用户的Guid得到用户对象。 /// </summary> /// <param name="guid">Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByGuid(Guid guid, string userName, string password) { return GetUserByPath(Utils.GenerateADsPath(guid), userName, password); } /// <summary> /// 根据用户的Guid得到用户对象,使用默认用户身份标识。 /// </summary> /// <param name="guid">Guid</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByGuid(Guid guid) { return GetUserByGuid(guid, null, null); } /// <summary> /// 根据用户的DN得到用户对象。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByDN(string dn, string userName, string password) { return GetUserByPath(dn, userName, password); } /// <summary> /// 根据用户的DN得到用户对象,使用默认用户身份标识。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByDN(string dn) { return GetUserByDN(dn, null, null); } /// <summary> /// 根据用户的ADsPath得到用户对象。 /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByPath(string path, string userName, string password) { DirectoryEntry entry = GetByPath(path, userName, password); if (entry != null) { User user = new User(entry); entry.Close(); entry.Dispose(); return user; } else return null; } /// <summary> /// 根据用户的ADsPath得到用户对象,使用默认用户身份标识。 /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> public static User GetUserByPath(string path) { return GetUserByPath(path, null, null); } #endregion #region Password /// <summary> /// 设置用户密码。 /// </summary> /// <param name="guid">用户DirectoryEntry的Guid。</param> /// <param name="newPassword">新密码。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void SetUserPassword(Guid guid, string newPassword, string userName, string password) { DirectoryEntry de = null; try { de = GetByGuid(guid, userName, password); if (de == null) throw new EntryNotExistException("用户对象不存在。"); if (de.SchemaClassName != SchemaClass.user.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.user.ToString("F") + "。"); de.Invoke("SetPassword", new object[] { newPassword }); de.CommitChanges(); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 设置用户密码,使用默认用户身份标识。 /// </summary> /// <param name="guid">用户DirectoryEntry的Guid。</param> /// <param name="newPassword">新密码。</param> public static void SetUserPassword(Guid guid, string newPassword) { SetUserPassword(guid, newPassword, null, null); } #endregion #region Move /// <summary> /// 移动用户DirectoryEntry到指定位置。 /// </summary> /// <param name="userPath">要移动的用户DirectoryEntry的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void MoveUser(string userPath, string newLocationPath, bool mustOU, string userName, string password) { if (!Exists(userPath)) throw new EntryNotExistException("需要被移动的对象不存在。"); DirectoryEntry de = null; try { de = GetByPath(userPath, userName, password); MoveUser(de, newLocationPath, mustOU, userName, password); } catch { throw; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 移动用户DirectoryEntry到指定位置,使用默认用户身份标识。 /// </summary> /// <param name="userPath">要移动的用户DirectoryEntry的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> public static void MoveUser(string userPath, string newLocationPath, bool mustOU) { MoveUser(userPath, newLocationPath, mustOU, null, null); } /// <summary> /// 移动用户DirectoryEntry到指定位置。 /// </summary> /// <param name="user">要移动的用户DirectoryEntry的Guid</param> /// <param name="newLocation">移动到的位置的Guid</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void MoveUser(Guid user, Guid newLocation, bool mustOU, string userName, string password) { MoveUser(GetUserByGuid(user).Dn, GetOUByGuid(newLocation).Dn, mustOU, userName, password); } /// <summary> /// 移动用户DirectoryEntry到指定位置,使用默认用户身份标识。 /// </summary> /// <param name="user">要移动的用户DirectoryEntry的Guid</param> /// <param name="newLocation">移动到的位置的Guid</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> public static void MoveUser(Guid user, Guid newLocation, bool mustOU) { MoveUser(GetUserByGuid(user).Dn, GetOUByGuid(newLocation).Dn, mustOU, null, null); } /// <summary> /// 移动用户DirectoryEntry到指定位置。 /// </summary> /// <param name="de">要移动的用户DirectoryEntry对象。必须是通过DN形式路径得到的对象。</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式。完全转义过的。</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> internal static void MoveUser(DirectoryEntry de, string newLocationPath, bool mustOU, string userName, string password) { if (!Exists(newLocationPath)) throw new EntryNotExistException("移动到的位置对象不存在。"); DirectoryEntry newLocation = null; try { newLocation = GetByPath(newLocationPath, userName, password); if (de.SchemaClassName != SchemaClass.user.ToString("F")) throw new SchemaClassException("需要被移动的对象类型不是" + SchemaClass.user.ToString("F") + "。"); if (mustOU && newLocation.SchemaClassName != SchemaClass.organizationalUnit.ToString("F")) throw new SchemaClassException("移动到的位置对象类型不是" + SchemaClass.organizationalUnit.ToString("F") + "。"); if (Exists(Utils.GetRDNValue(de.Properties[BaseObject.PROPERTY_DN].Value.ToString()) + "," + newLocation.Properties[BaseObject.PROPERTY_DN].Value.ToString())) throw new SameRDNException("移动到的位置下存在同名对象。"); de.MoveTo(newLocation); de.CommitChanges(); } catch (InvalidOperationException ioe) // 指定的 DirectoryEntry 不是容器。 { throw new NotContainerException(ioe.Message, ioe); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (newLocation != null) { newLocation.Close(); newLocation.Dispose(); } } } #endregion #region MemberOf /// <summary> /// 获取用户DirectoryEntry对象的PrimaryGroup DirectoryEntry对象。 /// </summary> /// <param name="userPath">用户DirectoryEntry的ADsPath。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>不存在返回null。</returns> public static DirectoryEntry GetUserPrimaryGroup(string userPath, string userName, string password) { DirectoryEntry de = GetByPath(userPath, userName, password); if (de == null) throw new EntryNotExistException("用户对象不存在。"); if (de.SchemaClassName != SchemaClass.user.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.user.ToString("F") + "。"); return GetUserPrimaryGroup(de, userName, password); } /// <summary> /// 获取用户DirectoryEntry对象的PrimaryGroup DirectoryEntry对象,使用默认用户身份标识。 /// </summary> /// <param name="userPath">用户DirectoryEntry的ADsPath。</param> /// <returns>不存在返回null。</returns> public static DirectoryEntry GetUserPrimaryGroup(string userPath) { return GetUserPrimaryGroup(userPath, null, null); } /// <summary> /// 获取用户DirectoryEntry对象的PrimaryGroup DirectoryEntry对象。 /// </summary> /// <param name="user">用户DirectoryEntry对象。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>不存在返回null。</returns> internal static DirectoryEntry GetUserPrimaryGroup(DirectoryEntry user, string userName, string password) { string primaryGroupSID = User.GeneratePrimaryGroupSID((byte[])(user.Properties[BaseObject.PROPERTY_OBJECTSID].Value), Convert.ToInt32(user.Properties[User.PROPERTY_MEMBEROF_PRIMARY].Value)); return GetBySid(primaryGroupSID, userName, password); } /// <summary> /// 获取用户DirectoryEntry对象的隶属组的DN。 /// </summary> /// <param name="userPath">用户DirectoryEntry的ADsPath。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <param name="includePrimaryGroup">是否包括PrimaryGroup</param> /// <returns>不存在返回空集合。</returns> public static List<string> GetUserMemberOfDN(string userPath, string userName, string password, bool includePrimaryGroup) { DirectoryEntry de = GetByPath(userPath, userName, password); if (de == null) throw new EntryNotExistException("用户对象不存在。"); if (de.SchemaClassName != SchemaClass.user.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.user.ToString("F") + "。"); List<string> dn = new List<string>(); if (includePrimaryGroup) { DirectoryEntry primary = GetUserPrimaryGroup(de, userName, password); if (primary != null) { dn.Add(Utils.EscapeDNBackslashedChar(primary.Properties[BaseObject.PROPERTY_DN].Value.ToString())); primary.Close(); primary.Dispose(); } } if (de.Properties.Contains(User.PROPERTY_MEMBEROF_ALL)) { foreach (object m in de.Properties[User.PROPERTY_MEMBEROF_ALL]) { dn.Add(Utils.EscapeDNBackslashedChar(m.ToString())); // 转义/ } } de.Close(); de.Dispose(); return dn; } /// <summary> /// 获取用户DirectoryEntry对象的隶属组的DN,使用默认用户身份标识。 /// </summary> /// <param name="userPath">用户DirectoryEntry的ADsPath。</param> /// <param name="includePrimaryGroup">是否包括PrimaryGroup</param> /// <returns>不存在返回空集合。</returns> public static List<string> GetUserMemberOfDN(string userPath, bool includePrimaryGroup) { return GetUserMemberOfDN(userPath, null, null, includePrimaryGroup); } #endregion #endregion #region Group #region Search /// <summary> /// 获取指定所有组。 /// </summary> /// <param name="cn">组CN。</param> /// <param name="description">组描述。</param> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static List<Group> SearchGroup(string cn, string description, string rootPath, string userName, string password) { string schema = null; if (!String.IsNullOrEmpty(cn) || !String.IsNullOrEmpty(description)) schema = String.Format("(&{0}{1})", (!String.IsNullOrEmpty(cn) ? String.Format("(cn=*{0}*)", Utils.Escape4Query(cn)) : "" ), (!String.IsNullOrEmpty(description) ? String.Format("(description=*{0}*)", Utils.Escape4Query(description)) : "")); List<DirectoryEntry> entries = Search(schema, "group", null, rootPath, SearchScope.Subtree, userName, password); List<Group> groups = new List<Group>(); foreach (DirectoryEntry de in entries) { groups.Add(new Group(de)); de.Close(); de.Dispose(); } return groups; } /// <summary> /// 获取指定所有组,使用默认用户身份标识。 /// </summary> /// <param name="cn">组CN。</param> /// <param name="description">组描述。</param> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> public static List<Group> SearchGroup(string cn, string description, string rootPath) { return SearchGroup(cn, description, rootPath, null, null); } /// <summary> /// 获取指定所有组。 /// </summary> /// <param name="cn">组CN。</param> /// <param name="description">组描述。</param> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass。 /// 最后添加了sAMAccountName。</remarks> public static List<String[]> SearchGroupSimple(string cn, string description, string rootPath, string userName, string password) { string schema = null; if (!String.IsNullOrEmpty(cn) || !String.IsNullOrEmpty(description)) schema = String.Format("&{0}{1}", (!String.IsNullOrEmpty(cn) ? String.Format("(cn=*{0}*)", Utils.Escape4Query(cn)) : ""), (!String.IsNullOrEmpty(description) ? String.Format("(cn=*{0}*)", Utils.Escape4Query(description)) : "")); return Search2(schema, "group", null, rootPath, SearchScope.Subtree, userName, password); } /// <summary> /// 获取指定所有组,使用默认用户身份标识。 /// </summary> /// <param name="cn">组CN。</param> /// <param name="description">组描述。</param> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass</remarks> public static List<String[]> SearchGroupSimple(string cn, string description, string rootPath) { return SearchGroupSimple(cn, description, rootPath, null, null); } /// <summary> /// 获取指定所有组。直接解析查询结果,速度较SearchGroup快。 /// </summary> /// <param name="cn">组CN。</param> /// <param name="description">组描述。</param> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static List<Group> SearchGroupQuick(string cn, string description, string rootPath, string userName, string password) { string schema = null; if (!String.IsNullOrEmpty(cn) || !String.IsNullOrEmpty(description)) schema = String.Format("&{0}{1}", (!String.IsNullOrEmpty(cn) ? String.Format("(cn=*{0}*)", Utils.Escape4Query(cn)) : ""), (!String.IsNullOrEmpty(description) ? String.Format("(cn=*{0}*)", Utils.Escape4Query(description)) : "")); SearchResultCollection results = Search3(schema, "group", null, rootPath, SearchScope.Subtree, userName, password); List<Group> groups = new List<Group>(); foreach (SearchResult se in results) { groups.Add(new Group(se)); } return groups; } /// <summary> /// 获取指定所有组,使用默认用户身份标识。直接解析查询结果,速度较SearchGroup快。 /// </summary> /// <param name="cn">组CN。</param> /// <param name="description">组描述。</param> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> public static List<Group> SearchGroupQuick(string cn, string description, string rootPath) { return SearchGroupQuick(null,null, rootPath, null, null); } /// <summary> /// 根据sAMAccountName获取Group。 /// </summary> /// <param name="sAMAccountName">sAMAccountName。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupBySAMAccountName(string sAMAccountName, string userName, string password) { List<DirectoryEntry> entries = Search("sAMAccountName=" + Utils.Escape4Query(sAMAccountName), "group", null, null, SearchScope.Subtree, userName, password); if (entries.Count == 1) { DirectoryEntry de = entries[0]; Group group = new Group(de); de.Close(); de.Dispose(); return group; } return null; } #endregion #region Get /// <summary> /// 根据用户的Guid得到组对象。 /// </summary> /// <param name="guid">Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupByGuid(Guid guid, string userName, string password) { return GetGroupByPath(Utils.GenerateADsPath(guid), userName, password); } /// <summary> /// 根据用户的Guid得到组对象,使用默认用户身份标识。 /// </summary> /// <param name="guid">Guid</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupByGuid(Guid guid) { return GetGroupByGuid(guid, null,null); } /// <summary> /// 根据用户的DN得到用户组。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupByDN(string dn, string userName, string password) { return GetGroupByPath(dn, userName, password); } /// <summary> /// 根据用户的DN得到组对象,使用默认用户身份标识。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupByDN(string dn) { return GetGroupByDN(dn, null, null); } /// <summary> /// 根据用户的ADsPath得到组对象。 /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupByPath(string path, string userName, string password) { DirectoryEntry entry = GetByPath(path, userName, password); if (entry != null) { Group group = new Group(entry); entry.Close(); entry.Dispose(); return group; } else return null; } /// <summary> /// 根据用户的ADsPath得到组对象,使用默认用户身份标识。 /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> public static Group GetGroupByPath(string path) { return GetGroupByPath(path, null, null); } #endregion #region Rename /// <summary> /// 更改组DirectoryEntry对象的名称。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath</param> /// <param name="newName">该项的新名称。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void RenameGroup(string groupPath, string newName, string userName, string password) { DirectoryEntry de = GetByPath(groupPath, userName, password); if (de == null) throw new EntryNotExistException("组对象不存在。"); if (de.SchemaClassName != SchemaClass.group.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.group.ToString("F") + "。"); string dn = Utils.EscapeDNBackslashedChar(de.Properties[BaseObject.PROPERTY_DN].Value.ToString()); string rdn = Utils.GenerateRDNCN(newName); if(Exists(Utils.GenerateDN(rdn, Utils.GetParentDN(dn)))) throw new SameRDNException("已存在同名对象。"); try { de.Rename(rdn); de.CommitChanges(); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 更改组DirectoryEntry对象的名称,使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath</param> /// <param name="newName">该项的新名称。</param> public static void RenameGroup(string groupPath, string newName) { RenameGroup(groupPath, newName); } #endregion #region Member Change /// <summary> /// 将用户添加到组。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <param name="userDN">需要添加的用户的DN。完全转义的。</param> public static void AddUserToGroup(string groupPath, string userName, string password, params string[] userDN) { DirectoryEntry de = GetByPath(groupPath, userName, password); if (de == null) throw new EntryNotExistException("组对象不存在。"); if (de.SchemaClassName != SchemaClass.group.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.group.ToString("F") + "。"); // 得到已有的Member List<string> ms = new List<string>(); foreach (object m in de.Properties[Group.PROPERTY_MEMBER]) { ms.Add(Utils.EscapeDNBackslashedChar(m.ToString())); } ms.Sort(); // 已排序 -- 以便内部使用 List<string> toAdd = new List<string>(); foreach (string udn in userDN) { if (!(ms.BinarySearch(udn) >= 0)) { if (!toAdd.Exists(delegate(string a ) {return a == udn;})) toAdd.Add(udn); } } try { foreach (string udn in toAdd) { de.Invoke("Add", new object[] { ParaMgr.LDAP_IDENTITY + udn }); // 需要ADsPath } de.CommitChanges(); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 将用户添加到组,使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userDN">需要添加的用户的DN。</param> public static void AddUserToGroup(string groupPath, params string[] userDN) { AddUserToGroup(groupPath, null,null,userDN); } /// <summary> /// 将用户添加到组。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <param name="userGuid">需要添加的用户的Guid。</param> public static void AddUserToGroup(string groupPath, string userName, string password, params Guid[] userGuid) { List<string> userDN = new List<string>(); User user = null; foreach(Guid guid in userGuid) { user = GetUserByGuid(guid); if (user != null) { userDN.Add(user.Dn); } } AddUserToGroup(groupPath, userName, password, userDN.ToArray()); } /// <summary> /// 将用户添加到组,使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userGuid">需要添加的用户的Guid。</param> public static void AddUserToGroup(string groupPath, params Guid[] userGuid) { AddUserToGroup(groupPath, null, null, userGuid); } /// <summary> /// 将用户从组中移除。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <param name="userDN">需要移除的用户的DN。完全转义的。</param> public static void RemoveUserFromGroup(string groupPath, string userName, string password, params string[] userDN) { DirectoryEntry de = GetByPath(groupPath, userName, password); if (de == null) throw new EntryNotExistException("组对象不存在。"); if (de.SchemaClassName != SchemaClass.group.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.group.ToString("F") + "。"); // 得到已有的Group List<string> ms = new List<string>(); foreach (object m in de.Properties[Group.PROPERTY_MEMBER]) { ms.Add(Utils.EscapeDNBackslashedChar(m.ToString())); } ms.Sort(); // 已排序 -- 以便内部使用 List<string> toRemove = new List<string>(); foreach (string udn in userDN) { if (ms.BinarySearch(udn) >= 0) { if (!toRemove.Exists(delegate(string a) { return a == udn; })) toRemove.Add(udn); } } try { foreach (string udn in toRemove) { de.Invoke("Remove", new object[] { ParaMgr.LDAP_IDENTITY + udn }); // 需要ADsPath } //de.Invoke("Remove", userDN); // TODO:是否需要保留转义的/,是否需要ADsPath,like AddUserToGroup de.CommitChanges(); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 将用户从组中移除,使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userDN">需要移除的用户的DN。</param> public static void RemoveUserFromGroup(string groupPath, params string[] userDN) { RemoveUserFromGroup(groupPath, null,null,userDN); } /// <summary> /// 将用户从组中移除。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <param name="userGuid">需要移除的用户的Guid。</param> public static void RemoveUserFromGroup(string groupPath, string userName, string password, params Guid[] userGuid) { List<string> userDN = new List<string>(); User user = null; foreach(Guid guid in userGuid) { user = GetUserByGuid(guid); if (user != null) { userDN.Add(user.Dn); } } RemoveUserFromGroup(groupPath, userName, password, userDN.ToArray()); } /// <summary> /// 将用户从组中移除,使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userGuid">需要移除的用户的Guid。</param> public static void RemoveUserFromGroup(string groupPath, params Guid[] userGuid) { RemoveUserFromGroup(groupPath, null, null, userGuid); } #endregion #region MemberOf & Member /// <summary> /// 获取组的隶属组的DN /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public static List<string> GetGroupMemberOfDN(string groupPath, string userName, string password) { DirectoryEntry de = GetByPath(groupPath, userName, password); if (de == null) throw new EntryNotExistException("组对象不存在。"); if (de.SchemaClassName != SchemaClass.group.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.group.ToString("F") + "。"); List<string> dn = new List<string>(); if (de.Properties.Contains(Group.PROPERTY_MEMBEROF)) { foreach (object m in de.Properties[Group.PROPERTY_MEMBEROF]) { dn.Add(Utils.EscapeDNBackslashedChar(m.ToString())); } } de.Close(); de.Dispose(); return dn; } /// <summary> /// 获取组的隶属组的DN,使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <returns></returns> public static List<string> GetGroupMemberOfDN(string groupPath) { return GetGroupMemberOfDN(groupPath, null, null); } /// <summary> /// 获取组的成员(仅用户) /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public static List<User> GetGroupUserMember(string groupPath, string userName, string password) { DirectoryEntry de = GetByPath(groupPath, userName, password); if (de == null) throw new EntryNotExistException("组对象不存在。"); if (de.SchemaClassName != SchemaClass.group.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.group.ToString("F") + "。"); List<User> users = new List<User>(); string userSchemaClassName = SchemaClass.user.ToString("F"); if (de.Properties.Contains(Group.PROPERTY_MEMBER)) { foreach (object memberDN in de.Properties[Group.PROPERTY_MEMBER]) { de = GetByDN(Utils.EscapeDNBackslashedChar(memberDN.ToString()), userName, password); if (de != null) { if (de.SchemaClassName == userSchemaClassName) { users.Add(new User(de)); } de.Close(); de.Dispose(); } } } return users; } /// <summary> /// 获取组的成员(仅用户),使用默认用户身份标识。 /// </summary> /// <param name="groupPath">组DirectoryEntry的ADsPath。完全转义的。</param> /// <returns></returns> public static List<User> GetGroupUserMember(string groupPath) { return GetGroupUserMember(groupPath, null, null); } #endregion #endregion #region OU #region Search /// <summary> /// 获取指定所有组织单位。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static List<OU> GetOUAll(string rootPath, string userName, string password) { List<DirectoryEntry> entries = Search(null, "organizationalUnit", null, rootPath, SearchScope.Subtree, userName, password); List<OU> ous = new List<OU>(); foreach (DirectoryEntry de in entries) { ous.Add(new OU(de)); de.Close(); de.Dispose(); } return ous; } /// <summary> /// 获取指定所有组织单位,使用默认用户身份标识。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> public static List<OU> GetOUAll(string rootPath) { return GetOUAll(rootPath, null, null); } /// <summary> /// 获取指定所有组织单位。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass</remarks> public static List<String[]> GetOUAllSimple(string rootPath, string userName, string password) { return Search2(null, "organizationalUnit", null, rootPath, SearchScope.Subtree, userName, password); } /// <summary> /// 获取指定所有组织单位,使用默认用户身份标识。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> /// <remarks>包括distinguishedname,objectguid,name,description,adspath,objectcategory,objectclass</remarks> public static List<String[]> GetOUAllSimple(string rootPath) { return GetOUAllSimple(rootPath, null, null); } /// <summary> /// 获取指定所有组织单位。直接解析查询结果,速度较GetUserAll快。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static List<OU> GetOUAllQuick(string rootPath, string userName, string password) { SearchResultCollection results = Search3(null, "organizationalUnit", null, rootPath, SearchScope.Subtree, userName, password); List<OU> ous = new List<OU>(); foreach (SearchResult se in results) { ous.Add(new OU(se)); } return ous; } /// <summary> /// 获取指定所有组织单位,使用默认用户身份标识。直接解析查询结果,速度较GetUserAll快。 /// </summary> /// <param name="rootPath">根对象ADsPath,null表示整个域。</param> /// <returns>如果不存在,返回null。</returns> public static List<OU> GetOUAllQuick(string rootPath) { return GetOUAllQuick(rootPath, null, null); } #endregion #region Get /// <summary> /// 根据组织单位的Guid得到组织单位对象。 /// </summary> /// <param name="guid">Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static OU GetOUByGuid(Guid guid, string userName, string password) { return GetOUByPath(Utils.GenerateADsPath(guid), userName, password); } /// <summary> /// 根据组织单位的Guid得到组织单位对象,使用默认用户身份标识。 /// </summary> /// <param name="guid">Guid</param> /// <returns>如果不存在,返回null。</returns> public static OU GetOUByGuid(Guid guid) { return GetOUByGuid(guid, null, null); } /// <summary> /// 根据组织单位的DN得到组织单位对象。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static OU GetOUByDN(string dn, string userName, string password) { return GetOUByPath(dn, userName, password); } /// <summary> /// 根据组织单位的DN得到组织单位对象,使用默认用户身份标识。 /// </summary> /// <param name="dn">DN。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> public static OU GetOUByDN(string dn) { return GetOUByDN(dn, null, null); } /// <summary> /// 根据组织单位的ADsPath得到组织单位对象。 /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static OU GetOUByPath(string path, string userName, string password) { DirectoryEntry entry = GetByPath(path, userName, password); if (entry != null) { OU ou = new OU(entry); entry.Close(); entry.Dispose(); return ou; } else return null; } /// <summary> /// 根据组织单位的ADsPath得到组织单位对象,使用默认用户身份标识。 /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <returns>如果不存在,返回null。</returns> public static OU GetOUByPath(string path) { return GetOUByPath(path, null, null); } #endregion #region Rename /// <summary> /// 更改组织单位DirectoryEntry对象的名称。 /// </summary> /// <param name="ouPath">组织单位DirectoryEntry的ADsPath。必须是DN形式,且完全转义。</param> /// <param name="newName">该项的新名称。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void RenameOU(string ouPath, string newName, string userName, string password) { DirectoryEntry de = GetByPath(ouPath, userName, password); if (de == null) throw new EntryNotExistException("组织单位对象不存在。"); if (de.SchemaClassName != SchemaClass.organizationalUnit.ToString("F")) throw new SchemaClassException("对象类型不是" + SchemaClass.organizationalUnit.ToString("F") + "。"); string dn = Utils.EscapeDNBackslashedChar(de.Properties[BaseObject.PROPERTY_DN].Value.ToString()); string rdn = Utils.GenerateRDNOU(newName); if (Exists(Utils.GenerateDN(rdn, Utils.GetParentDN(dn)))) throw new SameRDNException("已存在同名对象。"); try { de.Rename(rdn); de.CommitChanges(); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 更改组DirectoryEntry对象的名称,使用默认用户身份标识。 /// </summary> /// <param name="ouPath">组织单位DirectoryEntry的ADsPath。必须是DN形式,且完全转义。</param> /// <param name="newName">该项的新名称。</param> public static void RenameOU(string ouPath, string newName) { RenameOU(ouPath, newName, null, null); } /// <summary> /// 更改组织单位DirectoryEntry对象的名称。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <param name="newName">该项的新名称。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void RenameOU(Guid ouGuid, string newName, string userName, string password) { RenameOU(TB.ADBlock.ADManager.GetOUByGuid(ouGuid).Dn, newName, userName, password); } /// <summary> /// 更改组织单位DirectoryEntry对象的名称,使用默认用户身份标识。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的ADsPath</param> /// <param name="newName">该项的新名称。</param> public static void RenameOU(Guid ouGuid, string newName) { RenameOU(Utils.GenerateADsPath(ouGuid), newName, null, null); } #endregion #region Move /// <summary> /// 移动组织单位DirectoryEntry到指定位置。 /// </summary> /// <param name="ouPath">要移动的组织单位DirectoryEntry的ADsPath。必须是DN形式,且完全转义。</param> /// <param name="newLocationPath">移动到的位置的ADsPath。必须是DN形式,且完全转义。</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void MoveOU(string ouPath, string newLocationPath, bool mustOU, string userName, string password) { if (!Exists(ouPath)) throw new EntryNotExistException("需要被移动的对象不存在。"); DirectoryEntry de = null; try { de = GetByPath(ouPath, userName, password); MoveOU(de, newLocationPath, mustOU, userName, password); } catch { throw; } finally { if (de != null) { de.Close(); de.Dispose(); } } } /// <summary> /// 移动组织单位DirectoryEntry到指定位置,使用默认用户身份标识。 /// </summary> /// <param name="ouPath">要移动的组织单位DirectoryEntry的ADsPath</param> /// <param name="newLocationPath">移动到的位置的ADsPath</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> public static void MoveOU(string ouPath, string newLocationPath, bool mustOU) { MoveUser(ouPath, newLocationPath, mustOU, null, null); } /// <summary> /// 移动组织单位DirectoryEntry到指定位置。 /// </summary> /// <param name="ou">要移动的组织单位DirectoryEntry的Guid</param> /// <param name="newLocation">移动到的位置的Guid</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> public static void MoveOU(Guid ou, Guid newLocation, bool mustOU, string userName, string password) { MoveUser(TB.ADBlock.ADManager.GetOUByGuid(ou).Dn, TB.ADBlock.ADManager.GetOUByGuid(newLocation).Dn, mustOU, userName, password); } /// <summary> /// 移动组织单位DirectoryEntry到指定位置,使用默认用户身份标识。 /// </summary> /// <param name="ou">要移动的组织单位DirectoryEntry的Guid</param> /// <param name="newLocationPath">移动到的位置的Guid</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> public static void MoveOU(Guid ou, Guid newLocationPath, bool mustOU) { MoveUser(ou, newLocationPath, mustOU, null, null); } /// <summary> /// 移动组织单位DirectoryEntry到指定位置。 /// </summary> /// <param name="de">要移动的组织单位DirectoryEntry对象</param> /// <param name="newLocationPath">移动到的位置的ADsPath</param> /// <param name="mustOU">移动到的位置对应的DirectoryEntry是否必须是组织单位。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> internal static void MoveOU(DirectoryEntry de, string newLocationPath, bool mustOU, string userName, string password) { if (!Exists(newLocationPath)) throw new EntryNotExistException("移动到的位置对象不存在。"); DirectoryEntry newLocation = null; try { newLocation = GetByPath(newLocationPath, userName, password); if (de.SchemaClassName != SchemaClass.organizationalUnit.ToString("F")) throw new SchemaClassException("需要被移动的对象类型不是" + SchemaClass.organizationalUnit.ToString("F") + "。"); if (mustOU && newLocation.SchemaClassName != SchemaClass.organizationalUnit.ToString("F")) throw new SchemaClassException("移动到的位置对象类型不是" + SchemaClass.organizationalUnit.ToString("F") + "。"); if (Exists(Utils.GetRDNValue(de.Properties[BaseObject.PROPERTY_DN].Value.ToString()) + "," + newLocation.Properties[BaseObject.PROPERTY_DN].Value.ToString())) throw new SameRDNException("移动到的位置下存在同名对象。"); de.MoveTo(newLocation); de.CommitChanges(); } catch (InvalidOperationException ioe) // 指定的 DirectoryEntry 不是容器。 { throw new NotContainerException(ioe.Message, ioe); } catch (DirectoryServicesCOMException dsce) { throw dsce; } finally { if (newLocation != null) { newLocation.Close(); newLocation.Dispose(); } } } #endregion #region Structure /// <summary> /// 获取组织单位子树。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public OU GetOUSubTree(Guid ouGuid, string userName, string password) { OU ou = GetOUByGuid(ouGuid); if (ou == null) throw new EntryNotExistException("组织单位对象不存在。"); return ou.GetSubTree(userName, password); } /// <summary> /// 获取组织单位子树,使用默认用户身份标识。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <returns></returns> public OU GetOUSubTree(Guid ouGuid) { return GetOUSubTree(ouGuid, null, null); } /// <summary> /// 获取组织单位子组织单位。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public List<OU> GetOUChildren(Guid ouGuid, string userName, string password) { OU ou = GetOUByGuid(ouGuid); if (ou == null) throw new EntryNotExistException("组织单位对象不存在。"); return ou.GetChildren(userName, password); } /// <summary> /// 获取组织单位子组织单位,使用默认用户身份标识。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <returns></returns> public List<OU> GetOUChildren(Guid ouGuid) { return GetOUChildren(ouGuid, null, null); } /// <summary> /// 获取组织单位父组织单位。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns></returns> public OU GetOUParent(Guid ouGuid, string userName, string password) { OU ou = GetOUByGuid(ouGuid); if (ou == null) throw new EntryNotExistException("组织单位对象不存在。"); return ou.GetParent(userName, password); } /// <summary> /// 获取组织单位父组织单位,使用默认用户身份标识。 /// </summary> /// <param name="ouGuid">组织单位DirectoryEntry的Guid</param> /// <returns></returns> public OU GetOUParent(Guid ouGuid) { return GetOUParent(ouGuid, null, null); } #endregion #endregion /// <summary> /// 通过ADsPath获取对象。目前仅限User,OU和Group /// </summary> /// <param name="path">ADsPath。完全转义过的。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回null。</returns> public static BaseObject GetObjectByPath(string path, string userName, string password) { BaseObject baseObject = null; DirectoryEntry entry = GetByPath(path, userName, password); if (entry != null) { SchemaClass schema = SchemaClass.none; try { schema = (SchemaClass)(Enum.Parse(typeof(SchemaClass), entry.SchemaClassName)); switch (schema) { case SchemaClass.user: baseObject = new User(entry); break; case SchemaClass.group: baseObject = new Group(entry); break; case SchemaClass.organizationalUnit: baseObject = new OU(entry); break; } } catch { } entry.Close(); entry.Dispose(); return baseObject; } else return null; } /// <summary> /// 指定的SAMAccountName用户或组是否存在。 /// </summary> /// <param name="sAMAccountName">sAMAccountName</param> /// <param name="an">如果存在,对应的sAMAccountName。</param> /// <param name="dn">如果存在,对应的DN。</param> /// <param name="precision">true表示完全匹配,false表示前向匹配。</param> /// <param name="userName">用户身份标识--用户名。为空时使用默认用户身份标识。</param> /// <param name="password">用户身份标识--密码。</param> /// <returns>如果不存在,返回false。</returns> public static bool SAMAccountNameExists(string sAMAccountName, out string an, out string dn, bool precision, string userName, string password) { an = null; dn = null; List<DirectoryEntry> entries = Search("sAMAccountName=" + Utils.Escape4Query(sAMAccountName) + "*", null, null, null, SearchScope.Subtree, userName, password); if (entries.Count >= 1) { string schemaClassName = entries[0].SchemaClassName; bool valid = ((schemaClassName == SchemaClass.group.ToString("F")) || (schemaClassName == SchemaClass.user.ToString("F"))); if (valid) { an = entries[0].Properties["sAMAccountName"].Value.ToString(); if ((precision && (an == sAMAccountName)) || (!precision)) { dn = Utils.EscapeDNBackslashedChar(entries[0].Properties[BaseObject.PROPERTY_DN].Value.ToString()); } else { an = null; valid = false; } } entries[0].Close(); entries[0].Dispose(); return valid; } return false; } } }