Reputation: 4504
I want to load the assembly via the following
var loadedAssembly = Assembly.Load(File.ContentsAsBytes);
the File.ContentAsBytes returns the dll as a byte[]
, via the following
System.IO.File.ReadAllBytes("dll location");
The issue is the loaded assembly (loadedAssembly
) loses its phyisical location
Is there a way to load from a byte[]
and getting a similar result to Assembly.LoadFile
as I need the the result to work with the AppDomain.CurrentDomain.AssemblyResolve
Upvotes: 14
Views: 3769
Reputation: 49179
Sure, you'd think that Location would have a set method somewhere that you could access or some other way to tweak it. It doesn't. What happens (I dropped mscorlib.dll into IL DASM) is that when you load from file, there is a native handle that it associated with the assembly in the class RuntimeAssembly. When you call the Location getter, it grabs this handle and gives you the location from the native handle, but only if there was one. No handle, no location.
Here's the 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
Upvotes: 3
Reputation: 36053
A byte array byte[]
is simply a stream of bytes in memory. It has no correlation to any file at all. That byte array could have been read from file, downloaded from a web server, or created spontaneously by a random number generator. There is no extra data that "goes with it".
If you want to maintain the file location where the byte array was originally read from, then you must maintain that data separately in another variable. There is no way to "attach" the extra data to the byte[]
variable.
When you use Assembly.Load
to load the byte array as an assembly, it has no way to know where that byte array came from, because that extra data is not provided to the Load
function.
As a workaround, is there a way you can save your byte array to a temporary file, use Assembly.LoadFile
to give you the data you need and link the Location
back to your original byte array?
Upvotes: 5
Reputation: 87218
Once you pass the byte[]
to the Assembly.Load
method, that byte array has absolutely no information to even hint the Load
method where it came from - it's only a bunch of bytes. The same would apply if you copied the file to a separate location:
File.Copy(dllLocation, anotherLocation);
var asm = Assembly.LoadFile(anotherLocation);
The assembly location will be pointing to anotherLocation
, even though the assembly originally was on dllLocation
. Similarly, when you load the assembly bytes (essentially copying the assembly from the disk to memory), the "location" of those bytes is now the memory.
Upvotes: 2