Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MEF loading plugins from a network shared folder

Tags:

c#

mef

Tearing my hair out trying to work out why Im having this problem so hope someone can help.

I have a program that uses MEF to load plugins. I would like the client and server part of the system to be able to use the same plugin store that will be located on the server.

My problem is that when I set the plugin location to "C:\Users\Administrator\Desktop\ClientPlugins" the plugin is loaded fine. If I change the location to "\\XRP-SERVER\Users\Administrator\Desktop\ClientPlugins" the plugin is not loaded.

When I enter "\\XRP-SERVER\Users\Administrator\Desktop\ClientPlugins" into windows explorer the location is found and the plugin dll is there.

Please could someone help.

Let me know if you require anymore information.

As per a suggestion I have tried editing the config to include the following but this has not fixed the issues....

  <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <loadFromRemoteSources enabled="true"/>
      </runtime>

Kind Regards

Ash

like image 752
user589195 Avatar asked Nov 09 '11 10:11

user589195


3 Answers

Security policies will typically disable loading remote code (that being, assemblies on an external location).

You can try the following config change:

<runtime>
    <loadFromRemoteSources enabled="true"/>
</runtime>

The other thing to be aware of is when you are copying files back from network locations, they will typically have a Zone specified in their alternate data stream. In explorer, this can be removed by using the "Unblock" command when viewing the properties of a file.

Alternatively, you could programatically remove the Zone from the alternate data stream, as shown here on Mike Hadlow's blog.

like image 78
Matthew Abbott Avatar answered Nov 07 '22 14:11

Matthew Abbott


I ran into this problem yesterday and narrowed the problem down to how MEF loads assemblies. When you create a DirectoryCatalog, it in turns creates a collection of AssemblyCatalogs. Each AssemblyCatalog does an:

    AssemblyName assemblyName = AssemblyName.GetAssembly();
    Assembly.Load(assemblyName);

The call to Assembly.Load throws a sandbox Exception (for a reason I can't explain yet) and therefore no parts are found since it silently catches the error.

The funny thing is that calling Assembly.LoadFrom(<pathToYourDll>) to return an Assembly works fine (no exception is thrown). Combine that with the overloaded constructor of AssemblyCatalog that takes an Assembly as its input and you got yourself a workaround!

So instead of using a DirectoryCatalog, I list all the DLLs in the path and iteratively create an AssemblyCatalog and add it to my CompositionContainer.

Note : I am using the loadFromRemoteSources="true" flag in my App.Config and it is required, otherwise it always crashes.

Hope this helps

like image 20
sebd Avatar answered Nov 07 '22 12:11

sebd


Just to clarify sebd's answer works.

Heres the final code I used.

string[] files = Directory.GetFiles(ClientPluginStore, "*.dll", SearchOption.TopDirectoryOnly);

AggregateCatalog aggCat = new AggregateCatalog();

aggCat.Catalogs.Add(catalog);

foreach ( string file in files )
{
    Assembly ass = Assembly.LoadFrom(file);

    AssemblyCatalog assCat = new AssemblyCatalog(ass);

    aggCat.Catalogs.Add(assCat);
}

_container = new CompositionContainer(aggCat);
like image 3
user589195 Avatar answered Nov 07 '22 13:11

user589195