我有一个部分信任的AppDomain,我在其中运行一个完全信任的调试窗口。使用PermissionSetAttribute
获取权限我可以创建窗口并使用它做很多事情,但有时在数据绑定期间会抛出SecurityException。
一个易于重现的案例抛出了这个:Property accessor 'Namespace' on object 'System.RuntimeType' threw the following exception:'Request failed.'
。挖掘异常,我可以看到,当需要完全信任时,它就被抛出了。
没问题,调试窗口程序集完全信任,我只需要断言它。但是当我查看内部SecurityException
的堆栈跟踪时,我看到了这一点:
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessSecurityEngine.Check(PermissionSet permSet, StackCrawlMark& stackMark)
at System.Security.PermissionSet.Demand()
at System.SecurityUtils.DemandGrantSet(Assembly assembly)
at System.SecurityUtils.DemandReflectionAccess(Type type)
at System.SecurityUtils.MethodInfoInvoke(MethodInfo method, Object target, Object[] args)
at System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component)
它就在ReflectPropertyDescriptor.GetValue
处结束。
在Visual Studio的调用堆栈窗口中,我可以在堆栈的最顶端看到ReflectPropertyDescriptor.GetValue
。 那个堆栈一直回到调试窗口的创建和我在那里执行的安全断言,这正是我想要的。
为什么堆栈被分成两个这样的?我怎么能阻止它发生?
我正在使用.Net 4.0安全性(即第2级)。
答案 0 :(得分:1)
这不奇怪。 Visual Studio的调用堆栈向您显示抛出当前异常时的方法。 InnerException
显示出现内部异常异常的调用堆栈。在抛出内部异常之后,它会向上传播callstack,从而展开它直到它到达ReflectPropertyDescriptor.GetValue
。此时,它被捕获在一个catch块中,并被设置为新异常的内部异常,然后抛出并冒泡一直向上。因此,第二个异常的调用堆栈从它被抛出的点开始(即ReflectPropertyDescriptor.GetValue
)
这是一个简单的例子,可以重现这一点。
namespace Exceptions
{
class ExceptionTester
{
public void Run()
{
ThrowSecondException();
}
public void DoSomething()
{
DoMore();
}
public void DoMore()
{
ThrowFirstException();
}
public void ThrowFirstException()
{
throw new FooException();
}
public void ThrowSecondException()
{
try
{
DoSomething();
}
catch (FooException e)
{
throw new BarException("derp", e);
}
}
}
class FooException : Exception
{
}
class BarException : Exception
{
public BarException(string msg, Exception inner) : base(msg, inner)
{
}
}
class Program
{
static void Main(string[] args)
{
var tester = new ExceptionTester();
tester.Run();
}
}
}
当抛出类型BarException
的第二个异常时,您会注意到visual studio在调用堆栈的顶部有ThrowSecondException
,因为这是抛出BarException
的地方。但是,当您深入BarException's
InnerException
并查看FooException's
调用堆栈时,它会向您显示抛出FooException
的位置(ThrowFirstException()
)。