通过Bytes加载程序集会丢失位置

本文关键字:位置 程序集 Bytes 加载 通过 | 更新日期: 2023-09-27 18:14:14

我想通过下面的

加载程序集

var loadedAssembly = Assembly.Load(File.ContentsAsBytes);

文件。ContentAsBytes返回dll作为byte[],通过以下

System.IO.File.ReadAllBytes("dll location");

问题是加载的程序集(loadedAssembly)丢失了它的物理位置

  • loadedAssembly。CodeBase -被设置为正在加载它的程序集(这是不正确的)
  • loadedAssembly。位置-为空

是否有一种方法可以从byte[]加载并获得与Assembly.LoadFile类似的结果,因为我需要结果与AppDomain.CurrentDomain.AssemblyResolve一起工作

通过Bytes加载程序集会丢失位置

字节数组byte[]只是内存中的字节流。它与任何文件都没有关联。字节数组可以从文件中读取,从web服务器下载,或者由随机数生成器自发创建。没有额外的数据"与它一起"。

如果您想维护最初读取字节数组的文件位置,那么您必须在另一个变量中单独维护该数据。没有办法将额外的数据"附加"到byte[]变量。

当你使用Assembly.Load将字节数组作为程序集加载时,它无法知道字节数组来自哪里,因为额外的数据没有提供给Load函数。

作为一种解决方案,是否有一种方法可以将字节数组保存到临时文件,使用Assembly.LoadFile为您提供所需的数据,并将Location链接回原始字节数组?

当然,您会认为 Location应该在某个地方有一个set方法,您可以访问或以其他方式调整它。它不是。发生的事情(我将mscorlib.dll放入IL DASM)是,当您从文件加载时,有一个本机句柄,它与类RuntimeAssembly中的程序集相关联。当你调用Location getter时,它会抓取这个句柄并从本机句柄中给你位置,但前提是有一个。没有句柄,没有位置

这是IL:

.method public hidebysig specialname virtual 
    instance string  get_Location() cil managed
{
  .custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       37 (0x25)
  .maxstack  3
  .locals init (string V_0)
  IL_0000:  ldnull
  IL_0001:  stloc.0
  IL_0002:  ldarg.0
  IL_0003:  call       instance class System.Reflection.RuntimeAssembly System.Reflection.RuntimeAssembly::GetNativeHandle()
  IL_0008:  ldloca.s   V_0
  IL_000a:  call       valuetype System.Runtime.CompilerServices.StringHandleOnStack System.Runtime.CompilerServices.JitHelpers::GetStringHandleOnStack(string&)
  IL_000f:  call       void System.Reflection.RuntimeAssembly::GetLocation(class System.Reflection.RuntimeAssembly,
                                                                       valuetype System.Runtime.CompilerServices.StringHandleOnStack)
  IL_0014:  ldloc.0
  IL_0015:  brfalse.s  IL_0023
  IL_0017:  ldc.i4.8
  IL_0018:  ldloc.0
  IL_0019:  newobj     instance void System.Security.Permissions.FileIOPermission::.ctor(valuetype System.Security.Permissions.FileIOPermissionAccess,
                                                                                     string)
  IL_001e:  call       instance void System.Security.CodeAccessPermission::Demand()
  IL_0023:  ldloc.0
  IL_0024:  ret
} // end of method RuntimeAssembly::get_Location

一旦您将byte[]传递给Assembly.Load方法,该字节数组绝对没有任何信息甚至提示Load方法它来自哪里-它只是一堆字节。如果您将该文件复制到另一个位置,则同样适用:

File.Copy(dllLocation, anotherLocation);
var asm = Assembly.LoadFile(anotherLocation);

程序集的位置将指向anotherLocation,即使程序集最初是在dllLocation上。类似地,当您加载程序集字节(本质上是将程序集从磁盘复制到内存)时,这些字节的"位置"现在是内存。