Take the 2-minute tour ×

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

  • loadedAssembly.CodeBase - is set to the assembly which is loading it (which is not correct)
  • loadedAssembly.Location - is empty

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

share|improve this question
That's the whole point. This has deep security implication. An assembly identity is not just represented by its bytes. Where it was loaded from (disk, internet, etc.) is crucial. You can't pretend a given set of byte is, say, mscorlib.dll. The only way would be to save it to a temp file and load it from there, which could work with AssemblyResolve, but that raises the question to why would you want to do this in the first place? –  Simon Mourier May 19 '13 at 6:51
I don't know what your context is, but isn't it an option to keep track of a dictionary yourself? –  Grimace of Despair May 22 '13 at 7:23
@SimonMourier the work around is already thought of, and can be used in my scenario, but the application would be far more flexible if I could accomplish the above. –  dbones May 22 '13 at 19:59
@GrimaceofDespair already done, although you cannot override how .NET uses AssemblyResolve when loading assemblies and the dependent assemblies. the issue is the AssemblyResolve does not fire if it thinks it has the assembly loaded –  dbones May 22 '13 at 20:03
Result of Assembly.Load(byte[]) should work with AppDomain.CurrentDomain.AssemblyResolve. Why do you say "as I need the the result to work with the AppDomain.CurrentDomain.AssemblyResolve"? –  Stipo May 25 '13 at 20:57
add comment

4 Answers

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?

share|improve this answer
thanks, already aware of this solution, also it has been suggested by @carlosfigueira and in the comments. Consider that the LoadFile needs to do the same under the covers. I just need to find a way that will work with AssemblyResolve, unless there is an alternative to AssemblyResolve. –  dbones May 23 '13 at 17:48
add comment

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
  // 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,
  IL_001e:  call       instance void System.Security.CodeAccessPermission::Demand()
  IL_0023:  ldloc.0
  IL_0024:  ret
} // end of method RuntimeAssembly::get_Location
share|improve this answer
add comment

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.

share|improve this answer
thanks, that's how I understood the issue, however when you load it in from the byte[], is their a way to provide any Meta-data. As the loadFile must load the assembly in memory and at some point supply meta-data. –  dbones May 16 '13 at 21:08
add comment

I faced a similar situation. It's rare that I actually need the location, but for the cases that I do, I created a helper class (AssemblyUtilities) that I use to load the bytes for the assembly and just store the location in a static Dictionary. An additional helper method (GetLocation) peeks through to the assembly's actual location, and if there isn't one, consults the dictionary. This works fine since I'm responsible for loading the raw bytes anyway, and the peek-through handles assemblies loaded in the "traditional" way. Like so...

public static class AssemblyUtilities {
    private static Dictionary<Assembly, string> locationByAssembly =
        new Dictionary<Assembly, string>();

    private static Dictionary<string, Assembly> assemblyByLocation =
        new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);

    public static Assembly LoadFile(string location) {
        Assembly assembly;
        lock (locationByAssembly) {
            if (!assemblyByLocation.TryGetValue(location, out assembly)) {
                byte[] bytes = ReadAllBytes(location);
                if (bytes == null) return null;
                byte[] pdb = ReadAllBytes(Path.ChangeExtension(location, ".pdb"));
                assembly = ((pdb == null)? Assembly.Load(bytes): Assembly.Load(bytes, pdb));
                locationByAssembly[assembly] = location;
                assemblyByLocation[location] = assembly;
            return assembly;

    public static string GetLocation(Assembly assembly) {
        if (assembly == null) return null;
        string location = assembly.Location;
        if (location == null) locationByAssembly.TryGetValue(assembly, out location);
        return location;

    private static byte[] ReadAllBytes(string path) {
        try { return File.ReadAllBytes(path); }
        catch { return null; }

// And if you prefer extensions...
public static class AssemblyExtensions {
    public static string GetLocation(this Assembly self) {
        return AssemblyUtilities.GetLocation(self);
share|improve this answer
Could you post an example of what you are talking about? This answer is somewhat confusing as is. –  BradleyDotNET Apr 11 at 17:46
Briefly, here's what I have: public static class AssemblyUtilities { private static Dictionary<Assembly, string> locationByAssembly = ...; public static Assembly LoadFile(string loc) { byte[] bytes = ReadAllBytes(loc); byte[] pdb = ReadAllBytes(Path.ChangeExtension(loc, ".pdb")); Assembly a = ((pdb == null)? Assembly.Load(bytes): Assembly.Load(bytes, pdb)); locationByAssembly[a] = loc; return a; } public static string GetLocation(Assembly a) { string loc = a.Location; if (loc == null) locationByAssembly.TryGetValue(a, out loc); return loc; } } –  the7thchakra Apr 17 at 17:42
Pardon the crappy formatting. I used the back tick, but it ate the newlines. Meh. –  the7thchakra Apr 17 at 17:44
That looks great! Add it to your answer (improve the formatting of course) and I would be happy to upvote. (Code in comments is really hard to read :) ) –  BradleyDotNET Apr 17 at 17:47
add comment

Your Answer


