Satellite assembly and AssemblyResolve event

In .Net framework, CLR will not raise AssemblyResolve event for missing satellite assemblies (to be precise, Resource Manager asks CLR loader to not raise AssemblyResolve event if it can’t find a satellite assembly.). The reason is that Resource Manager has many by-design assembly loading failures. It will unnecessarily flood the AssemblyResolve event handler to raise AssemblyResolve event for every satellite assembly loading failure.


This brings up a question:


How to return satellite assembly for assemblies returned from AssemblyResolve event?


For example, we have the following deployment:






App.exe tries to load myasm.dll, which won’t be found in C:\MyApp. An AssemblyResolve handler is invoked, and myasm.dll is returned from C:\Others\myasm.dll. Now myasm.dll wants to use its zh-cn satellite assembly. Since the assembly won’t be found in C:\MyApp, and CLR won’t raise AssemblyResolve for the satellite assembly, how can we return the satellite assembly?


The answer is, use Assembly.LoadFrom in the AssemblyResolve handler to return myasm.dll.


When an assembly load is requested is in the LoadFrom context, CLR will probe the assembly in the parent assembly’s directory, in additional to the application base. Therefore, the satellite assembly in C:\others will be found by CLR automatically.

Comments (13)

  1. Max C says:

    Do you have any advice on preventing unnecessary resource probing for OBJECT-tag hosted managed controls in Internet Explorer? These HTTP requests are obviously very expensive. At present I’m placing a zero-length file where the first probe attempt is made.

  2. Max,

    I’ll ask our resource guys to see if there is any guideline on this.

  3. Max C says:

    Splendid, thanks Junfeng.

  4. Alex says:

    Is there any chance to load an assembly with all dependencies via AssemblyResolve method only?

    Here is the case where I need that.

    All assemblies of a component are stored in DB. Main application uses the component and implement AppDomain.AssemblyResolve event handler. When the framework raises the event handler loads an assembly. If there is a need to load a couple of assemblies (recursively) I’ve got System.FileNotFoundException exception. It seems framework is trying to find an assembly by default resolving schema while I’m expecting AssemblyResolve event to be raised.

    Thank you in advance.

  5. Alex,

    Can you show an example?

  6. Alex says:

    I’m sorry, may I provide a sample now or is this thread already closed? Thank you.

  7. Alex says:

    I have a question I guess is related to the problem.

    I create additional AppDomain and subscribe for AsemblyResolve event. The class that provides handler is derived from MarshalByRefObject.

    1. Handler method (instance) private: an exception is raised while an assembly is being resolved.

    2. Handler method (instance) public: the same exception.

    3. Handler method static public: everything is fine.

    I have to make some bad architecture moves to support static handler method.

    Is there any way to make it work with instance handler?

    Thank you

  8. Here is the reply I get from the loader dev:

    "Is he trying to provide the resolve handler for one appdomain from another appdomain?

    Because if he is, I have bad news for him – subscribing to AssemblyResolve from another appdomain doesn’t work as the result cannot be marshaled (Assembly class is not MarshalByRef).

    The reason (3) appears to work is because the static method is actually called in that additional appdomain not in the original one(it’s been marshaled when subscribing to the event) so there is no actual appdomain transition there and our inability to marshal the Assembly object does not come into play.


  9. Alex says:

    Thank you.

    I applyed SerializableAttribute (instead of inheritance from MarshalByRefObject) and it seems the resolving is working fine. Also an instance resolver method is used.

    May be there are drawbacks, but I’ve not found them yet.


Skip to main content