2012-01-04 13 views
6

पृष्ठभूमि

में UserPrinciapl.GetGroups बुला त्रुटि हम एक asp.net 4.0 वेब अनुप्रयोग सी # है कि एक .net 3.5 वेब सेवा सी # में लिखा कॉल में लिखा है। वेब सेवा उपयोगकर्ता आईडी को पास कर दी जाती है और उपयोगकर्ता द्वारा संबंधित सक्रिय निर्देशिका समूहों के आधार पर डेटा की एक सूची लौटाती है।अजीब रुक-रुक कर बग से निपटने जब System.DirectoryServices.AccountManagement

वेब सेवा सिस्टम के डायरेक्ट 3.5 संस्करण का उपयोग करती है। डायरेक्टरी सर्विसेज। खाता प्रबंधन उपयोगकर्ता के समूह के सिड्स प्राप्त करने के लिए प्रबंधन प्रबंधन।

उपयोगकर्ता प्रिंसिपल को कॉल करें। गेट समूह समूह की त्रुटि के साथ अंतःक्रियात्मक रूप से विफल हो जाते हैं। घटनाओं के बीच बहुत लंबी अवधि थी लेकिन जब ऐसा हुआ तो यह कई मिनटों के लिए बार-बार हुआ। यह मुद्दा विभिन्न एडी उपयोगकर्ताओं के लिए हुआ था।

इस अपवाद के ढेर का निशान हमें कोई समझ नहीं आया। हमने रिफ्लेक्टर/आईएलएसपी में माइक्रोसॉफ्ट एडी कोड को देखने में बहुत समय बिताया लेकिन आईएडीएसपीथनाम पर कॉल से परे नहीं जा सका। पुनः प्राप्त करें।

अपवाद

System.NotSupportedException: Specified method is not supported. 
at System.Web.HttpResponseStream.get_Position() 
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin) 
at System.DirectoryServices.AccountManagement.UnsafeNativeMethods.IADsPathname.Retrieve(Int32 lnFormatType) 
at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo() 
at System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsForestName() 
at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOf(Principal p) 
at System.DirectoryServices.AccountManagement.Principal.GetGroupsHelper() 
at System.DirectoryServices.AccountManagement.Principal.GetGroups() 
at Data.SoftwarePublishingItemData.GetSids(String requestedForUserId) 
at Data.SoftwarePublishingItemData.GetSoftwarePublishingItems(IDatabaseContext dbContext, GetSoftwarePublishingItemsSettings settings, XBXmlDocument parameters) 
at Web.GetSoftwarePublishingItems.GetFlexiFieldData(String xml) 

कोड पुन: पेश करने

कृपया ध्यान दें, CauseNotSupportedException विधि कोड की नकल उतार रहा है कि हमारे आवेदन में, लेकिन वातावरण में कहीं और कोड में है कि हम पर नहीं हैं नहीं चल रहा है इसका नियंत्रण। स्ट्रीम के

class Program 
{ 
    static void Main(string[] args) 
    { 
     CauseNotSupportedException(); 

     string samAccountName = "domain.user"; 

     using (var principalContext = new PrincipalContext(ContextType.Domain)) 
     { 
      using (var userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, samAccountName)) 
      { 
       if (userPrincipal == null) 
        throw new ActiveDirectoryObjectNotFoundException(); 

       using (var groups = userPrincipal.GetGroups()) 
       { 
        foreach (GroupPrincipal group in groups) 
        { 
         Console.WriteLine(group.Sid); 
        } 
       } 
      } 
     } 
    } 

    public static void CauseNotSupportedException() 
    { 
     using (var b = new Bitmap(500, 500, PixelFormat.Format32bppArgb)) 
     { 
      b.Save(new FakeStream(), ImageFormat.Png); 
     } 
    } 
} 

कार्यान्वयन HttpResponseStream नकल करने के लिए व्यवहार

public class FakeStream : Stream 
{ 
    public override bool CanRead { get { return false; } } 
    public override bool CanSeek { get { return false; } } 
    public override bool CanWrite { get { return true; } } 

    public override void Flush() { } 

    public override long Length { get { throw new NotSupportedException("No Seek"); } } 

    public override long Position 
    { 
     get { throw new NotSupportedException("No Seek"); } 
     set { throw new NotSupportedException("No Seek"); } 
    } 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     throw new InvalidOperationException("Write only stream"); 
    } 

    public override long Seek(long offset, SeekOrigin origin) 
    { 
     throw new NotSupportedException("net_noseek"); 
    } 

    public override void SetLength(long value) { } 

    public override void Write(byte[] buffer, int offset, int count) { } 
} 

प्रश्न

  1. आप त्रुटि है कि CauseNotSupportedException विधि में होता है ऊपर के उदाहरण चलाते हैं में फेंक दिया जाता है GetGroups को कॉल करें। ऐसे कैसे हो सकता है? किसी भी सिद्धांत या आगे की अंतर्दृष्टि की सराहना की जाएगी।
  2. आगे की जांच कैसे करें इसके बारे में कोई सुझाव?
  3. अपवाद को पकड़ने और पुनः प्रयास करने से बेहतर कोई सुझाव? यह हमारे वर्तमान काम के आसपास है।

धन्यवाद।

स्पष्टीकरण

मुझे यकीन है कि कैसे स्पष्ट मैं अपने स्पष्टीकरण में इसलिए यहाँ किया गया है कुछ स्पष्टीकरण है नहीं कर रहा हूँ। सबसे पहले, मैं सक्रिय निर्देशिका कोड से खुश हूं जो सिड्स प्राप्त करता है। यही वह है जो मैं चाहता हूं और मुझे नहीं लगता कि समस्या इस तरह है। असली मुद्दा यह है कि जब अन्य असंबद्ध कोड में कोई त्रुटि होती है (यह हमारे ऐप में नहीं है) त्रुटि गेट ग्रुप कॉल में प्रकट होती है, इसलिए मूल रूप से System.Web.HttpResponseStream.get_Position() पर होने वाली त्रुटि के साथ अजीब स्टैक ट्रेस होता है। नमूना ऐप में NotSupportedException CauseNotSupportedException में होता है लेकिन कोड वहां नहीं टूटता है, यह GetGroups को कॉल पर टूट जाता है। यदि आप नमूना ऐप में CauseNotSupportedException() को टिप्पणी करते हैं तो त्रुटि कभी नहीं होती है।

यह स्पष्ट नहीं है कि यह संभवतः कैसे हो सकता है।

+0

प्रश्न, क्या आप यह पता लगाने की कोशिश कर रहे हैं कि उपयोगकर्ता किसी विशेष समूह में हैं या नहीं .. मैं वास्तव में जो खोज रहा हूं उसके बारे में बेहतर समझ हासिल करने की कोशिश कर रहा हूं .. मेरे पास एक बेहतर दृष्टिकोण पर सुझाव हो सकता है कोडिंग .. यहां एक लिंक है जो मदद करेगा, साथ ही मैं नीचे 2 कोड स्निपेट पेस्ट करूँगा जो आपको आसानी से प्राप्त करने में मदद कर सकते हैं। http://msdn.microsoft.com/en-us/magazine/cc135979.aspx – MethodMan

+0

प्रतिक्रिया के लिए बहुत बहुत धन्यवाद। मुझे जो चाहिए वह समूह के सिड्स की एक सूची है जो उपयोगकर्ता का सदस्य है। मैं वर्तमान में System.DirectoryServices.AccountManagement नामस्थान का उपयोग कर रहा हूं (UserPrincipal.GetGroups उस नामस्थान में है)। तो मेरा कोड नमूना नीचे पोस्ट किए गए एक जैसा ही है। मुझे जो कोड मिला है वह ठीक हो गया है, यह केवल असंबद्ध कोड के कारण होने वाली अस्थायी त्रुटि है जिसे मैं समझने की कोशिश कर रहा हूं। यदि आपके पास समय है तो नमूना कोड चलाने और इसके माध्यम से कदम उठाने के लायक होंगे। –

+0

ठीक नहीं है .. सबसे पहले यह निर्धारित करना मुश्किल था कि आप क्या चाहते थे .. मेरी माफी आपको अभी भी उस संपत्ति या (स्ट्रिंग) गुणों ["samAccountName"] [0] की जांच करने की आवश्यकता होगी। ToString() क्योंकि यह इस समय एक वस्तु होगी .. उम्मीद है कि यह समझ में आता है .. – MethodMan

उत्तर

4

एक समर्थन कॉल बढ़ाने के बाद माइक्रोसॉफ्ट ने इस मुद्दे के लिए एक गर्म फिक्स जारी किया है। नीचे लिंक देखें।

घोषित कारण है:। "यह समस्या इसलिए होती है क्योंकि System.DirectoryServices.AccountManagement नाम स्थान देशी एपीआई सक्रिय निर्देशिका सेवा इंटरफ़ेस (ADSI) के लिए एक पतली आवरण है IErrorInfo इंटरफ़ेस IADsPathName इंटरफ़ेस द्वारा किया जाता है का जवाब अपवाद जो एडीएसआई फेंक नहीं देता है। जब स्टैक पर कोई एडीएसआई अपवाद नहीं होता है, तो IErrorInfo इंटरफ़ेस स्टैक के शीर्ष पर अपवाद फेंकता है, भले ही अपवाद को एप्लिकेशन में किसी अन्य हैंडलर द्वारा संभाला जाता है। "

http://support.microsoft.com/kb/2683913

जो लोग सुझाव की पेशकश करने के लिए धन्यवाद।

0

यदि आप .NET 3.5 या ऊपर हैं, तो आप नए System.DirectoryServices.AccountManagement (S.DS.AM) नामस्थान का उपयोग कर सकते हैं जो इसे होने से बहुत आसान बनाता है।

यहाँ यह सब के बारे में पढ़ें: [.NET फ्रेमवर्क 3.5 में प्रबंध निर्देशिका सुरक्षा प्रधानाध्यापकों] [1]

मूल रूप से, आप एक "प्रमुख संदर्भ" (आम तौर पर अपने डोमेन), एक उपयोगकर्ता प्रिंसिपल की आवश्यकता है, और फिर आप अपने समूहों को बहुत आसानी से मिल:

public List<GroupPrincipal> GetGroups(string userName) 
{ 
    List<GroupPrincipal> result = new List<GroupPrincipal>(); 

    // establish domain context 
    PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain); 

    // find your user 
    UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, username); 

    // if found - grab its groups 
    if(user != null) 
    { 
     PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups(); 

     // iterate over all groups 
     foreach(Principal p in groups) 
     { 
     // make sure to add only group principals or change this to add to a list or varible if needed. 
     if(p is GroupPrincipal) 
     { 
      result.Add(p); 
     } 
     } 
    } 

    return result; 
} 

कुछ गुण है, जो UserPrincipal वस्तु पर सामने नहीं कर रहे हैं का उपयोग करने के लिए, आप अंतर्निहित DirectoryEntry में खुदाई करने के लिए की जरूरत है:

public string GetDepartment(Principal principal) 
{ 
    string result = string.Empty; 

    DirectoryEntry de = (principal.GetUnderlyingObject() as DirectoryEntry); 

    if (de != null) 
    { 
     if (de.Properties.Contains("samAccountName")) 
     { 
      result = de.Properties["samAccountName"][0].ToString(); 
     } 
    } 

    return result; 
} 

//Change this Method to fit what ever your needs desire.. 
public string GetDepartment(string username) 
{ 
    string result = string.Empty; 

    // if you do repeated domain access, you might want to do this *once* outside this method, 
    // and pass it in as a second parameter! 
    PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain); 

    // find the user 
    UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, username); 

    // if user is found 
    if(user != null) 
    { 
     // get DirectoryEntry underlying it 
     DirectoryEntry de = (user.GetUnderlyingObject() as DirectoryEntry); 

     if (de != null) 
     { 
      if (de.Properties.Contains("department")) 
      { 
      result = de.Properties["department"][0].ToString(); 
      } 
     } 
    } 

    return result; 
} 
संबंधित मुद्दे