天天看點

活動目錄操作的一些方法

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://&lt;GUID&gt;兩種形式,但不限于這種形式。

    /// 一般方法均提供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;

        }

    }

}

繼續閱讀