1

我在锁定的 AppDomain 沙箱中运行代码。此 AppDomain 中抛出的异常不包括行号,即使 pdb 可用。尝试访问堆栈跟踪的代码是完全受信任的:程序集被签名并作为强程序集加载到应用程序域中。所以我希望堆栈跟踪包含文件名和行号。我不能将 AppDomain 标记为完全受信任,因为这会破坏沙盒的目的。如何让我的堆栈跟踪包含文件名和行号?

以下示例代码(基于此示例)显示了该问题。必须对包含的程序集进行签名,我已经在我的 github 上发布了示例应用程序。


using System;
using System.Security;
using System.Security.Policy;

namespace SandboxStacktrace
{
    public class Worker : MarshalByRefObject
    {
        private static void Main()
        {
            var w = new Worker();
            w.TestExceptionStacktrace();

            var adSandbox = GetInternetSandbox();
            var handle = Activator.CreateInstanceFrom(
                adSandbox,
                typeof(Worker).Assembly.ManifestModule.FullyQualifiedName,
                typeof(Worker).FullName);
            w = (Worker)handle.Unwrap();
            w.TestExceptionStacktrace();
        }

        public void TestExceptionStacktrace()
        {
            var ad = AppDomain.CurrentDomain;
            Console.WriteLine("\r\nApplication domain '{0}': IsFullyTrusted = {1}",
                ad.FriendlyName, ad.IsFullyTrusted);

            Console.WriteLine("   IsFullyTrusted = {0} for the current assembly",
                typeof(Worker).Assembly.IsFullyTrusted);

            Console.WriteLine("   IsFullyTrusted = {0} for mscorlib",
                typeof(int).Assembly.IsFullyTrusted);

            try
            {
                throw new Exception("Some exception");
            }
            catch (Exception e)
            {
                var trace = e.StackTrace;
                Console.Write("Stack trace contains {0}line numbers:\r\n{1}\r\n",
                    trace.Contains("line") ? "" : "no ", trace);
            }
        }

        // ------------ Helper method ---------------------------------------
        private static AppDomain GetInternetSandbox()
        {
            // Create the permission set to grant to all assemblies.
            var hostEvidence = new Evidence();
            hostEvidence.AddHostEvidence(new Zone(
                System.Security.SecurityZone.Internet));
            var pset =
                System.Security.SecurityManager.GetStandardSandbox(hostEvidence);

            // Identify the folder to use for the sandbox.
            var ads = new AppDomainSetup();
            ads.ApplicationBase = System.IO.Directory.GetCurrentDirectory();

            var fullTrustAssemblies = new[]
            {
                typeof(Worker).Assembly.Evidence.GetHostEvidence<StrongName>(),
            };

            // Create the sandboxed application domain.
            return AppDomain.CreateDomain("Sandbox", hostEvidence, ads, pset, fullTrustAssemblies);
        }
    }
}

这段代码的输出是:

Application domain 'SandboxStacktrace.exe': IsFullyTrusted = True
   IsFullyTrusted = True for the current assembly
   IsFullyTrusted = True for mscorlib
Stack trace contains line numbers:
   at SandboxStacktrace.Worker.NewMethod() in C:\Users\Bouke\Developer\SandboxStacktrace\Program.cs:line 44

Application domain 'Sandbox': IsFullyTrusted = False
   IsFullyTrusted = True for the current assembly
   IsFullyTrusted = True for mscorlib
Stack trace contains no line numbers:
   at SandboxStacktrace.Worker.NewMethod()
4

1 回答 1

0

Internet 区域非常严格。需要堆栈跟踪的 AppDomain 需要对文件本身进行一些访问,因此您需要在创建 AppDomain 时使用的权限集中添加一些文件权限,如下所示:

...

// add this to the permission set
pset.AddPermission(new FileIOPermission(
    FileIOPermissionAccess.PathDiscovery, typeof(Worker).Assembly.Location)
    );

return AppDomain.CreateDomain("Sandbox", hostEvidence, ads, pset, fullTrustAssemblies);

注意:当您遇到 CAS 问题时,您可以使用 AppDomain 的FirstChanceException 事件(或启用 Visual Studio 的所有异常,如果您使用它),它将向您显示内部吞下的错误。

于 2022-03-05T19:15:26.120 回答