Win10+VS2017下C# AppDomain因CodeAccessPermission报错,如何修复?
问题分析与修复方案
首先,你的异常根源是新创建的AppDomain权限集限制了对c:\git目录的文件操作,具体原因和修复步骤如下:
问题根源
你给secureDomain配置的权限集中,对整个c:\设置了FileIOPermissionAccess.NoAccess:
perm.AddPermission( new FileIOPermission(FileIOPermissionAccess.NoAccess, @"c:\"));
这意味着该AppDomain下运行的所有代码都无法访问C盘的任何位置,包括你要写入的c:\git目录。而ThirdParty的构造函数是在secureDomain中执行的(通过CreateInstanceAndUnwrap),自然会触发权限检查失败。
修复步骤
1. 调整文件权限设置
修改权限集,给c:\git目录授予写入+路径发现权限(路径发现权限PathDiscovery是解析目录路径必需的):
var perm = new PermissionSet(PermissionState.None); perm.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); // 替换原来的NoAccess设置,允许c:\git的写入和路径访问 perm.AddPermission(new FileIOPermission( FileIOPermissionAccess.Write | FileIOPermissionAccess.PathDiscovery, @"c:\git"));
2. 优化AppDomain对象的运行方式(可选但推荐)
你的ThirdParty标记为[Serializable],这会导致对象被序列化回当前AppDomain。如果希望ThirdParty的逻辑完全在secureDomain中执行,建议让它继承MarshalByRefObject,这样CreateInstanceAndUnwrap会返回一个代理,所有操作都会转发到目标域:
// 替换原来的Serializable标记,改为继承MarshalByRefObject public class ThirdParty : MarshalByRefObject { public ThirdParty() { Console.WriteLine("3p loading"); using (var file = System.IO.File.Create(@"c:\git\test.txt")) { // 建议using包裹File.Create,确保文件流被正确释放 } } }
3. 完整修改后的代码
class UseAppDomain { public static void Test() { var perm = new PermissionSet(PermissionState.None); perm.AddPermission( new SecurityPermission(SecurityPermissionFlag.Execution)); // 授予c:\git目录的写入和路径发现权限 perm.AddPermission(new FileIOPermission( FileIOPermissionAccess.Write | FileIOPermissionAccess.PathDiscovery, @"c:\git")); var setup = new AppDomainSetup(); setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; AppDomain secureDomain = AppDomain.CreateDomain("secure", null, setup, perm); Type thirdPartyType = typeof(ThirdParty); // 创建代理对象,逻辑在secureDomain中执行 secureDomain.CreateInstanceAndUnwrap(thirdPartyType.Assembly.FullName, thirdPartyType.FullName); AppDomain.Unload(secureDomain); } } public class ThirdParty : MarshalByRefObject { public ThirdParty() { Console.WriteLine("3p loading"); // 使用using确保文件流被释放,避免文件被占用 using (System.IO.File.Create(@"c:\git\test.txt")) { Console.WriteLine("文件创建成功"); } } }
额外注意事项
- 确保你的VS2017以管理员权限运行,否则即使代码权限设置正确,系统层面的UAC可能会阻止文件创建。
File.Create会返回一个文件流,务必释放它(用using包裹是最佳实践),否则文件会被锁定无法后续操作。
内容的提问来源于stack exchange,提问作者Troskyvs
相关产品推荐
相关产品推荐

