2009-09-16 77 views
3

是否有用于LDAP路径操作的.NET库?
我想有一些东西等于System.IO.Path,允许例如做类似.NET LDAP路径实用程序(C#)

string ou1 = LDAPPath.Combine("OU=users","DC=x,DC=y"); 
string ou2 = LDAPPath.Parent("CN=someone,OU=users,DC=x,DC=y"); 

否则,在.NET中处理LDAP专有名称的常见方法是什么?

澄清我的问题:我一般不会问“.NET中的目录服务”我已经使用过它并完成了一些程序来执行一些任务。我觉得缺少的是操纵路径,解析专有名称等等的正确方法,因为这应该是一个相当常见的需求,我希望有一个更简洁的方法来做到这一点,而不是在逗号(1)上分割一个字符串。 。

(1)等,例如,调用库中的函数,分割的逗号

+0

请参阅https://pscx.codeplex.com/SourceControl/latest#Trunk/Src/Pscx.UnitTests/DirectoryServices/DirectoryServicesTest.cs了解Powershell社区扩展 – 2014-04-29 16:14:46

+0

中使用的代码以及此相关问题http:// stackoverflow .com/a/23370901/17373 – 2014-04-29 17:34:43

回答

2

不,不是我的知识串 - 甚至在最近的.NET 3.5的命名空间为Active Directory。

您可以浏览目录本身的层级结构(转到父级等) - 但是您需要绑定到活动目录通过DirectoryEntry

然后是NameTranslate API,但这实际上更像是“将此名称更改为其他名称”,例如,从用户主体名称更改为相对DN - 并且需要连接到AD中的DirectoryEntry

我会对找到这样一个图书馆感兴趣,但到目前为止,我还没有听说过任何一个 - 无论是在.NET还是其他语言中,都没有。回到我的“重型”广告编程日,我有自己的一套LDAP路径操作例程(在Delphi中) - 基本上只是字符串解析和处理。

马克

+0

嗨marc_s,感谢您的回答......这或多或少是我猜到的。 – 2009-09-17 05:43:11

5

我使用基于关闭的Win32的方法DsGetRdnW,DsQuoteRdnValueW和DsUnquoteRdnValueW一对夫妇的工具类:

using System; 
using System.ComponentModel; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 

namespace UnmanagedCode 
{ 
    public class PInvoke 
    { 
     #region Constants 
     public const int ERROR_SUCCESS = 0; 
     public const int ERROR_BUFFER_OVERFLOW = 111; 
     #endregion Constants 

     #region DN Parsing 
     [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] 
     protected static extern int DsGetRdnW(
      ref IntPtr ppDN, 
      ref int pcDN, 
      out IntPtr ppKey, 
      out int pcKey, 
      out IntPtr ppVal, 
      out int pcVal 
     ); 

     public static KeyValuePair<string, string> GetName(string distinguishedName) 
     { 
      IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName); 
      try 
      { 
       IntPtr pDN = pDistinguishedName, pKey, pVal; 
       int cDN = distinguishedName.Length, cKey, cVal; 

       int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal); 

       if(lastError == ERROR_SUCCESS) 
       { 
        string key, value; 

        if(cKey < 1) 
        { 
         key = string.Empty; 
        } 
        else 
        { 
         key = Marshal.PtrToStringUni(pKey, cKey); 
        } 

        if(cVal < 1) 
        { 
         value = string.Empty; 
        } 
        else 
        { 
         value = Marshal.PtrToStringUni(pVal, cVal); 
        } 

        return new KeyValuePair<string, string>(key, value); 
       } 
       else 
       { 
        throw new Win32Exception(lastError); 
       } 
      } 
      finally 
      { 
       Marshal.FreeHGlobal(pDistinguishedName); 
      } 
     } 

     public static IEnumerable<KeyValuePair<string, string>> ParseDN(string distinguishedName) 
     { 
      List<KeyValuePair<string, string> components = new List<KeyValuePair<string, string>>(); 
      IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName); 
      try 
      { 
       IntPtr pDN = pDistinguishedName, pKey, pVal; 
       int cDN = distinguishedName.Length, cKey, cVal; 

       do 
       { 
        int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal); 

        if(lastError = ERROR_SUCCESS) 
        { 
         string key, value; 

         if(cKey < 0) 
         { 
          key = null; 
         } 
         else if(cKey == 0) 
         { 
          key = string.Empty; 
         } 
         else 
         { 
          key = Marshal.PtrToStringUni(pKey, cKey); 
         } 

         if(cVal < 0) 
         { 
          value = null; 
         } 
         else if(cVal == 0) 
         { 
          value = string.Empty; 
         } 
         else 
         { 
          value = Marshal.PtrToStringUni(pVal, cVal); 
         } 

         components.Add(new KeyValuePair<string, string>(key, value)); 

         pDN = (IntPtr)(pDN.ToInt64() + UnicodeEncoding.CharSize); //skip over comma 
         cDN--; 
        } 
        else 
        { 
         throw new Win32Exception(lastError); 
        } 
       } while(cDN > 0); 

       return components; 
      } 
      finally 
      { 
       Marshal.FreeHGlobal(pDistinguishedName); 
      } 
     } 

     [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] 
     protected static extern int DsQuoteRdnValueW(
      int cUnquotedRdnValueLength, 
      string psUnquotedRdnValue, 
      ref int pcQuotedRdnValueLength, 
      IntPtr psQuotedRdnValue 
     ); 

     public static string QuoteRDN(string rdn) 
     { 
      if (rdn == null) return null; 

      int initialLength = rdn.Length; 
      int quotedLength = 0; 
      IntPtr pQuotedRDN = IntPtr.Zero; 

      int lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN); 

      switch (lastError) 
      { 
       case ERROR_SUCCESS: 
        { 
         return string.Empty; 
        } 
       case ERROR_BUFFER_OVERFLOW: 
        { 
         break; //continue 
        } 
       default: 
        { 
         throw new Win32Exception(lastError); 
        } 
      } 

      pQuotedRDN = Marshal.AllocHGlobal(quotedLength * UnicodeEncoding.CharSize); 

      try 
      { 
       lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN); 

       switch(lastError) 
       { 
        case ERROR_SUCCESS: 
         { 
          return Marshal.PtrToStringUni(pQuotedRDN, quotedLength); 
         } 
        default: 
         { 
          throw new Win32Exception(lastError); 
         } 
       } 
      } 
      finally 
      { 
       if(pQuotedRDN != IntPtr.Zero) 
       { 
        Marshal.FreeHGlobal(pQuotedRDN); 
       } 
      } 
     } 


     [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] 
     protected static extern int DsUnquoteRdnValueW(
      int cQuotedRdnValueLength, 
      string psQuotedRdnValue, 
      ref int pcUnquotedRdnValueLength, 
      IntPtr psUnquotedRdnValue 
     ); 

     public static string UnquoteRDN(string rdn) 
     { 
      if (rdn == null) return null; 

      int initialLength = rdn.Length; 
      int unquotedLength = 0; 
      IntPtr pUnquotedRDN = IntPtr.Zero; 

      int lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN); 

      switch (lastError) 
      { 
       case ERROR_SUCCESS: 
        { 
         return string.Empty; 
        } 
       case ERROR_BUFFER_OVERFLOW: 
        { 
         break; //continue 
        } 
       default: 
        { 
         throw new Win32Exception(lastError); 
        } 
      } 

      pUnquotedRDN = Marshal.AllocHGlobal(unquotedLength * UnicodeEncoding.CharSize); 

      try 
      { 
       lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN); 

       switch(lastError) 
       { 
        case ERROR_SUCCESS: 
         { 
          return Marshal.PtrToStringUni(pUnquotedRDN, unquotedLength); 
         } 
        default: 
         { 
          throw new Win32Exception(lastError); 
         } 
       } 
      } 
      finally 
      { 
       if(pUnquotedRDN != IntPtr.Zero) 
       { 
        Marshal.FreeHGlobal(pUnquotedRDN); 
       } 
      } 
     } 
     #endregion DN Parsing 
    } 

    public class DNComponent 
    { 
     public string Type { get; protected set; } 
     public string EscapedValue { get; protected set; } 
     public string UnescapedValue { get; protected set; } 
     public string WholeComponent { get; protected set; } 

     public DNComponent(string component, bool isEscaped) 
     { 
      string[] tokens = component.Split(new char[] { '=' }, 2); 
      setup(tokens[0], tokens[1], isEscaped); 
     } 

     public DNComponent(string key, string value, bool isEscaped) 
     { 
      setup(key, value, isEscaped); 
     } 

     private void setup(string key, string value, bool isEscaped) 
     { 
      Type = key; 

      if(isEscaped) 
      { 
       EscapedValue = value; 
       UnescapedValue = PInvoke.UnquoteRDN(value); 
      } 
      else 
      { 
       EscapedValue = PInvoke.QuoteRDN(value); 
       UnescapedValue = value; 
      } 

      WholeComponent = Type + "=" + EscapedValue; 
     } 

     public override bool Equals(object obj) 
     { 
      if (obj is DNComponent) 
      { 
       DNComponent dnObj = (DNComponent)obj; 
       return dnObj.WholeComponent.Equals(this.WholeComponent, StringComparison.CurrentCultureIgnoreCase); 
      } 
      return base.Equals(obj); 
     } 

     public override int GetHashCode() 
     { 
      return WholeComponent.GetHashCode(); 
     } 
    } 

    public class DistinguishedName 
    { 
     public DNComponent[] Components 
     { 
      get 
      { 
       return components.ToArray(); 
      } 
     } 

     private List<DNComponent> components; 
     private string cachedDN; 

     public DistinguishedName(string distinguishedName) 
     { 
      cachedDN = distinguishedName; 
      components = new List<DNComponent>(); 
      foreach (KeyValuePair<string, string> kvp in PInvoke.ParseDN(distinguishedName)) 
      { 
       components.Add(new DNComponent(kvp.Key, kvp.Value, true)); 
      } 
     } 

     public DistinguishedName(IEnumerable<DNComponent> dnComponents) 
     { 
      components = new List<DNComponent>(dnComponents); 
      cachedDN = GetWholePath(","); 
     } 

     public bool Contains(DNComponent dnComponent) 
     { 
      return components.Contains(component); 
     } 

     public string GetDNSDomainName() 
     { 
      List<string> dcs = new List<string>(); 
      foreach (DNComponent dnc in components) 
      { 
       if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase)) 
       { 
        dcs.Add(dnc.UnescapedValue); 
       } 
      } 
      return string.Join(".", dcs.ToArray()); 
     } 

     public string GetDomainDN() 
     { 
      List<string> dcs = new List<string>(); 
      foreach (DNComponent dnc in components) 
      { 
       if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase)) 
       { 
        dcs.Add(dnc.WholeComponent); 
       } 
      } 
      return string.Join(",", dcs.ToArray()); 
     } 

     public string GetWholePath() 
     { 
      return GetWholePath(","); 
     } 

     public string GetWholePath(string separator) 
     { 
      List<string> parts = new List<string>(); 
      foreach (DNComponent component in components) 
      { 
       parts.Add(component.WholeComponent); 
      } 
      return string.Join(separator, parts.ToArray()); 
     } 

     public DistinguishedName GetParent() 
     { 
      if(components.Count == 1) 
      { 
       return null; 
      } 
      List<DNComponent> tempList = new List<DNComponent>(components); 
      tempList.RemoveAt(0); 
      return new DistinguishedName(tempList); 
     } 

     public override bool Equals(object obj) 
     { 
      if(obj is DistinguishedName) 
      { 
       DistinguishedName objDN = (DistinguishedName)obj; 
       if (this.Components.Length == objDN.Components.Length) 
       { 
        for (int i = 0; i < this.Components.Length; i++) 
        { 
         if (!this.Components[i].Equals(objDN.Components[i])) 
         { 
          return false; 
         } 
        } 
        return true; 
       } 
       return false; 
      } 
      return base.Equals(obj); 
     } 

     public override int GetHashCode() 
     { 
      return cachedDN.GetHashCode(); 
     } 
    } 
} 
0

虽然没有在.NET中没有LDAP路径分析器,有URI解析器。对于那些谁需要简单解析“LDAP://域名/ ...”的路径,你可以使用System.Uri类,那么你就可以得到这样的一些细节如下:

var uri = new Uri(SomeDomainURI); 
var scheme = uri.Scheme; // == "LDAP" or "LDAPS" usually 
var domainHost = uri.Host; 
var path = uri.AbsolutePath.TrimStart('/'); 

如果使用this DN parser你也可以而是做以下解析路径:

var dn = new DN(uri.AbsolutePath.TrimStart('/')); 

虽然我同意,.NET现在应该有这样的(!耻辱),这至少是一个好的解决办法满足我的需求,虽然并不完美,我怀疑它对每个人都足够强大。