2

I am using .NET reflection in order to inspect the content of an assembly. Unfortunately this is not that simple when it comes to inspecting types which are referenced by my assembly but are defined elsewhere.

So, say I have two Assembly:

Assembly assembly1 = Assembly.LoadFrom("MyAssembly.dll");
Assembly assembly2 = Assembly.LoadFrom("MyReferencedAssembly.dll");

In assembly1 there are types defined in assembly2 so what I want is basically loading assembly2 into assembly1.

How to achieve this programmatically?

Trying using AppDomain.Load

As suggested in comments, I am trying this:

private Assembly GetAssembly()
{
  string[] referencedAssemblyPaths = new[] { "MyReferencedAssembly.dll" };

  var domaininfo = new AppDomainSetup();
  domaininfo.ApplicationBase = Environment.CurrentDirectory;
  Evidence adevidence = AppDomain.CurrentDomain.Evidence;
  var domain = AppDomain.CreateDomain("AssemblyContextDomain", adevidence, domaininfo);

  Assembly assembly = domain.Load(LoadFile("MyAssembly.dll"));

  foreach (var path in referencedAssemblyPaths)
  {
    domain.Load(LoadFile(path));
  }

  return assembly;
}

private static byte[] LoadFile(string filename)
{
  FileStream fs = new FileStream(filename, FileMode.Open);
  byte[] buffer = new byte[(int)fs.Length];
  fs.Read(buffer, 0, buffer.Length);
  fs.Close();

  return buffer;
}

However I get a problem when invoking domain.Load(LoadFile("MyAssembly.dll")) as I get FileNotFoundException:

Could not load file or assembly 'MyAssembly, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

Debugging info By debugging I could see that the file exists in the correct place, LoadFile successfully returns the stream. The problem is in AppDomain.Load which throws that exception.

  • Why is it reporting it cannot find the file?
  • Is it trying to load the deendencies and those are the files it cannot find? But I will load dependencies right after...

How the hell am I supposed to load an assembly and its deps?

Andry
  • 16,172
  • 27
  • 138
  • 246
  • 2
    If i understand you correctly then you can use [AppDomain.AssemblyResolve](https://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve(v=vs.110).aspx) for this. Look here for details: http://stackoverflow.com/questions/24956949/assembly-loadfrom-and-dependencies or http://stackoverflow.com/questions/59220/how-do-i-load-an-assembly-and-all-of-its-dependencies-at-runtime-in-c-sharp-for –  May 07 '17 at 21:46
  • @elgonzo: Thanks for the suggestions. The second question seems promising but I would like to get some code as I can see a lot in the Internet. What approach would be recommended? That question is basically lacking some code examples, if you post an answer with that it would be very cool – Andry May 07 '17 at 21:50
  • Look at the MSDN documentation (link in my 1st comment) for an example. MSDN also has further documentation about AssemblyResolve events, such as: https://msdn.microsoft.com/en-us/library/ff527268(v=vs.110).aspx. Otherwise, Google is not far. Sorry, don't want to write an answer with code example, since i have no VS near me and i fear i can't write correct code from the top of my head with respect to assembly loading :( –  May 07 '17 at 21:52
  • The only time where you have type that not defined in assembly, is if that type used as variable or parameter. So, what .net does? - it walks the DLLs, GAC first, then bin, then local folders. So, you have to do same thing. Also see this http://stackoverflow.com/questions/23247521/get-type-information-for-type-declared-in-another-assembly-project – T.S. May 08 '17 at 00:36
  • Hi all. I have updated the question with more details and some code I have tried. – Andry May 08 '17 at 06:59

1 Answers1

1

When loading an assembly, .Net will automatically try to load all dependencies. The FileNotFoundException probably refers to 'one of its dependencies' not the actual assembly file - you can use fusion logging (How to enable assembly bind failure logging (Fusion) in .NET) to determine the exact failure reason. As suggested in comments, you can use AppDomain.AssemblyResolve to provide additional logic for finding referenced assemblies, but you need to actually attach the event to your domain which I don't see in your code - so domain.AssemblyResolve += .... This is usually only necessary when referenced assemblies are in a different folder or otherwise not found by the default search pattern, so if all you're after is debugging why it won't load then fusion log is the key.

AppDomains can be a bit tricky which is why they've been replaced/not implemented in .Net Core (https://blogs.msdn.microsoft.com/dotnet/2016/02/10/porting-to-net-core/).

If you want to load the assembly only to examine it first, without loading all the dependencies, you could load it for reflection only - https://msdn.microsoft.com/en-us/library/0et80c7k.aspx, which wouldn't allow you to execute any of the code in the assembly, so you'd need to do the actual load at some later point.

Community
  • 1
  • 1
Alex Paven
  • 5,539
  • 2
  • 21
  • 35