为什么我的堆栈跟踪被截断?

时间:2014-05-10 15:02:51

标签: c# wpf stack-trace code-access-security

我有一个部分信任的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级)。

1 个答案:

答案 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())。