最近遇到一个问题,在使用 Assembly.LoadFile 报错, 错误的消息是 访问拒绝!
涉及到dotnet的权限问题,我以前没接触结.果现在被老比尔干了,我现在干干他!
使用工具 vs2005 Reflector
为了方便起见,我已经将mscorlib 反编译了. 将其在vs2005 中打开.
ok let's go!
Assembly.LoadFile 方法

Code
1
public static Assembly LoadFile(string path)
2
{
3
new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand();
4
return nLoadFile(path, null);
5
}
6
7
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlEvidence)]
8
public static Assembly LoadFile(string path, System.Security.Policy.Evidence securityEvidence)
9
{
10
new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand();
11
return nLoadFile(path, securityEvidence);
12
}
哈哈 这是我调用的 Assembly.LoadFile(DLLFile.ToString());
有一个东东 FileIOPermission Permission 是么意思??
呵呵 似乎是它
再看看 nLoadFile 貌似 他才是关键

Code
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Assembly nLoadFile(string path, System.Security.Policy.Evidence evidence);
哈哈 一个原生方法
由此可以看出 Assembly.LoadFile ->nLoadFile
那末权限检查到底在哪里那?
答案就在 FileIOPermission 和 [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlEvidence)]
至于到底什么 不知道
那末如何解决这个问题那?
看全部打代码(太大了不贴了)
看LoadFrom 函数

Code
public static Assembly LoadFrom(string assemblyFile)
{
StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
return InternalLoadFrom(assemblyFile, null, null, AssemblyHashAlgorithm.None, false, ref lookForMyCaller);
}
public static Assembly LoadFrom(string assemblyFile, System.Security.Policy.Evidence securityEvidence)
{
StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
return InternalLoadFrom(assemblyFile, securityEvidence, null, AssemblyHashAlgorithm.None, false, ref lookForMyCaller);
}
public static Assembly LoadFrom(string assemblyFile, System.Security.Policy.Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
{
StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
return InternalLoadFrom(assemblyFile, securityEvidence, hashValue, hashAlgorithm, false, ref lookForMyCaller);
}
好像没有看到权限检查呀!
在看看InternalLoadFrom

Code
internal static Assembly InternalLoad(AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity, ref StackCrawlMark stackMark, bool forIntrospection)
{
if (assemblyRef == null)
{
throw new ArgumentNullException("assemblyRef");
}
assemblyRef = (AssemblyName) assemblyRef.Clone();
if (assemblySecurity != null)
{
new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
}
string strA = VerifyCodeBase(assemblyRef.CodeBase);
if (strA != null)
{
if (string.Compare(strA, 0, "file:", 0, 5, StringComparison.OrdinalIgnoreCase) != 0)
{
CreateWebPermission(assemblyRef.EscapedCodeBase).Demand();
}
else
{
URLString str2 = new URLString(strA, true);
new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, str2.GetFileName()).Demand();
}
}
return nLoad(assemblyRef, strA, assemblySecurity, null, ref stackMark, true, forIntrospection);
}
internal static Assembly InternalLoad(string assemblyString, System.Security.Policy.Evidence assemblySecurity, ref StackCrawlMark stackMark, bool forIntrospection)
{
if (assemblyString == null)
{
throw new ArgumentNullException("assemblyString");
}
if ((assemblyString.Length == 0) || (assemblyString[0] == '\0'))
{
throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
}
AssemblyName assemblyRef = new AssemblyName();
Assembly assembly = null;
assemblyRef.Name = assemblyString;
if (assemblyRef.nInit(out assembly, forIntrospection, true) == -2146234297)
{
return assembly;
}
return InternalLoad(assemblyRef, assemblySecurity, ref stackMark, forIntrospection);
}
private static Assembly InternalLoadFrom(string assemblyFile, System.Security.Policy.Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, bool forIntrospection, ref StackCrawlMark stackMark)
{
if (assemblyFile == null)
{
throw new ArgumentNullException("assemblyFile");
}
AssemblyName assemblyRef = new AssemblyName();
assemblyRef.CodeBase = assemblyFile;
assemblyRef.SetHashControl(hashValue, hashAlgorithm);
return InternalLoad(assemblyRef, securityEvidence, ref stackMark, forIntrospection);
}
呵呵 又是一大堆跳跳 InternalLoadFrom -> InternalLoad -> nLoad
最终 跳到

Code
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern Assembly _nLoad(AssemblyName fileName, string codeBase, System.Security.Policy.Evidence assemblySecurity, Assembly locationHint, ref StackCrawlMark stackMark, bool throwOnFileNotFound, bool forIntrospection);
呵呵优势一个 原生方法
最终解决 LoadFrom 代替 LoadFile
dotnet 的权限似乎 使用 某个类 或者 属性来控制的