【发布时间】:2012-02-02 10:24:13
【问题描述】:
背景
我们有一个用 C# 编写的 asp.net 4.0 Web 应用程序,它调用一个用 C# 编写的 .net 3.5 Web 服务。 Web 服务被传递一个用户 ID,并根据用户所属的活动目录组返回一个数据列表。
Web 服务使用 .net 3.5 版本的 System.DirectoryServices.AccountManagement 来获取用户所属组的 Sid。
对 UserPrincipal.GetGroups 的调用间歇性地失败,并出现以下错误。两次发生之间有很长的时间,但当它确实发生时,它会反复发生几分钟。不同的 AD 用户出现此问题。
这个异常的堆栈跟踪对我们来说毫无意义。我们花了很多时间查看 Reflector/ILSpy 中的 Microsoft AD 代码,但无法超越对 IADsPathName.Retrieve 的调用。
异常
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);
}
}
}
实现 Stream 以模仿 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) { }
}
问题
- 如果您运行上面的示例,则在调用 GetGroups 时会引发 CauseNotSupportedException 方法中发生的错误。这个怎么可能?任何理论或进一步的见解将不胜感激。
- 关于如何进一步调查的任何建议?
- 有比捕获异常并重试更好的建议吗?这是我们目前的工作。
谢谢。
澄清
我不确定我的解释有多清楚,所以这里有一些澄清。首先,我对获取 Sids 的活动目录代码感到满意。这就是我想要它做的事情,我认为问题不在于这样。真正的问题是,当其他不相关的代码(不在我们的应用程序中)发生错误时,错误会显示在 GetGroups 调用中,因此会出现奇怪的堆栈跟踪,错误最初发生在 System.Web.HttpResponseStream.get_Position() 中。在示例应用程序中 NotSupportedException 发生在 CauseNotSupportedException 但代码不会在那里中断,它会在调用 GetGroups 时中断。如果您在示例应用中注释掉 CauseNotSupportedException(),则永远不会发生错误。
我不清楚这怎么可能发生。
【问题讨论】:
-
问题,您是否要查找用户是否在特定组中。我试图更好地了解您真正在寻找什么。我可能有一个建议在编码方面更好的方法..这里有一个链接也会有所帮助,我将在下面粘贴 2 个代码 sn-ps,它应该可以帮助您更轻松地获得所需的内容。 msdn.microsoft.com/en-us/magazine/cc135979.aspx
-
非常感谢您的回复。我需要的是用户所属组的 Sid 列表。我目前正在使用 System.DirectoryServices.AccountManagement 命名空间(UserPrincipal.GetGroups 在该命名空间中)。所以我的代码示例与您在下面发布的非常相似。我的代码得到了我想要的,这只是我试图理解的不相关代码引起的间歇性错误。如果您有时间,值得运行示例代码并单步执行。
-
好吧没问题..一开始很难确定你想要什么..我很抱歉你仍然需要检查那个属性或 (string)Properties["samAccountName"][0 ].ToString() 因为此时这将是一个对象..希望这是有道理的..
-
抱歉,我发现很难写出这些提供足够信息但仍然清晰的东西。奇怪的是,当 CauseNotSupportedException 中发生错误时,它会跳转到 GetGroups 并在那里抛出异常。
-
如果不查看您的所有代码,我无法判断有很多方法可以获取您正在寻找的内容,但我正在努力为您提供答案,以帮助您了解您的代码,以防您需要修复或重构某些东西
标签: c# .net error-handling active-directory