C# appDomain 因 "CodeAccessPermission" 原因无法工作,为什么?

C# appDomain failed to work for "CodeAccessPermission" reason, why?

我正在使用 vs2017 在 win10 上尝试 C# appdomain,我有这个快速示例。我有一个名为 c:\git 的目录,我可以用 C# app 在这个目录下创建文件,但是当我尝试 app domain 时,它抛出异常,我的代码如下:

class UseAppDomain
{
    public static void Test()
    {
        var perm = new PermissionSet(PermissionState.None);
        perm.AddPermission(
            new SecurityPermission(SecurityPermissionFlag.Execution));
        perm.AddPermission(
            new FileIOPermission(FileIOPermissionAccess.NoAccess, @"c:\"));

        var setup = new AppDomainSetup();
        setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        AppDomain secureDomain = AppDomain.CreateDomain("secure", null, setup, perm);

        ThirdParty third = new ThirdParty();

        Type thirdParty = typeof(ThirdParty);
        secureDomain.
            CreateInstanceAndUnwrap(thirdParty.Assembly.FullName,
                thirdParty.FullName);  //exception!!!!!!!!!!
        AppDomain.Unload(secureDomain);
    }
}

[Serializable]
class ThirdParty
{
    public ThirdParty()
    {
        Console.WriteLine("3p loadling");
        System.IO.File.Create(@"c:\git\test.txt");//Try to create file failed!
    }
}

异常消息是:

Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark)
at System.Security.CodeAccessPermission.Demand()
... ...

我不太明白我的程序有什么问题,如何解决这个问题?

谢谢。

如果您想从部分受信任的域创建文件,您需要改用 FileIOPermissionAccess.Write。或者 FileIOPermissionAccess.AllAccess 如果您还想允许读取和目录内容发现。

旁注:

您将 CreateInstanceAndUnwrap 用于简单的可序列化 class,它不是从 MarshalByRefObject 派生的。它的效果是 class 将在创建的域中序列化,副本将在主域中反序列化,但是当您省略 return 值时,它无论如何都会被删除。

所以要么不要打开创建的对象,要么从 MarshalByRefObject class 派生它,这样它的 public 成员就可以通过远程处理从主域访问。