Assembly or file not found on plugin system C# - c#

I have a project that uses plugins based on an interface, they are coded in other "Class Library" projects in the same main project solution. The main project has a folder that contains all the plugins in dll format. So for example I have a Plugins folder in "Bin/Debug/". All the plugins are compiled on that directory.
Each plugin project has a reference to the main project as it uses the main framework (reference not copied locally).
Each plugin should be able to use methods from other plugins, here I have the problem.
Example:
I have PluginA and PluginB, 2 DLLs, 2 different projects but the DLLs are in the same Plugins folder.
Now I want to instantiate PluginB in PluginA class so I add a reference to PluginB DLL (not copied locally). No errors from the Compiler.
But when I istantiate PluginA on the main project after loading all the plugins assemblies, I get a System.IO.FileNotFoundException Assembly or file not found. (referred to PluginB)
Basically seems that when I call a Plugin, from the main project, that calls another Plugin, I get an error. I've also tried to use the Assembly Resolve event without success.
Maybe I made some mistakes with the entire plugins system, it's the first time I use them.
Sorry for my english, I'm italian.
Thanks for the help.

Related

Referencing a .dll that has already been merged with Fody/Costura

I have an app that references a .dll that was built with Costura/Fody i.e The dll has all its references embedded. When I run the console app, the references from the dll are not unpacked so the console app throws an exception saying missing .dll etc. as it needs those resources to run.
i.e. AssemblyA.dll embeds MyAssembly.dll when built with Costura/Fody. ConsoleAppC references and embeds AssemblyA.dll but also needs MyAssembly.dll to run. I do have a reference to MyAssembly.dll in ConsoleAppC so that it will compile (but CopyLocal is set to false). I was thinking that MyAssembly.dll would be made available to ConsoleAppC when AssemblyA.dll's embedded resources are unpacked?
This is not working but is my scenario valid in any way or can you only utilise embedded resources from ConsoleAppC and not the ones that were embedded in AssemblyA.dll?
Thanks in advance for any help
Mike
What you're trying to do isn't possible with Costura.Fody. What Costura does is embed libraries directly into the main assembly. This means that if you embed the built assembly into another project, it can't see the sub assemblies.
For example, consider the following project structure:
AssemblyA
Foo.cs
References:
SubAssembly1.dll
SubAssembly2.dll
SubAssembly3.dll
AssemblyB
Assume that Costura.Fody is used to embed the sub assemblies in AssemblyA, creating a single DLL file, AssemblyA.dll
If you embed AssemblyA.dll in AssemblyB, then you will not be able to access classes in SubAssembly1.dll. You will only be able to see any of the classes that are directly in AssemblyA.dll, such as those contained in Foo.cs - you will not be able to see any of the libraries referenced by/embedded in AssemblyA.dll.
See this answer to a similar question, where the answerer suggests using ILMerge instead.

Plugin architecture in C# with external dll like Open.XML from Nuget

I have created a plugin architecture in C# app. In special folder I upload dlls and system search for certain interface and using reflection invokes function within plugin. But one of plugins (dlls) references to Open.XML dll which is not installed on the server where app is running. Is it a way to create a plugin ( compile it ?) that contains all libraries that it needs. Or it should be done in a different way?
1) Distribute any required DLLs together with the plugin DLL, and put them inside the plugin folder. Either add the plugin folder to the probing path for assemblies in the app.config, or add a handler for the AssemblyResolve event.
2) Use ILMerge to combine the plugin and required assemblies into one assembly.
If you load all plugins into the same app domain, this will cause funny issues if the same types are merged into multiple plugins.

Reference other project in solution without separate dll

At the moment I have added and referenced another project to my main solution. It works, but then I need the separate dll that is compiled.
How can I reference another project without the need for a separate dll that I have to distribute with my final exe?
A C# class project in a Visual Studio solution always compiles to an assembly, so adding a project reference will inevitably mean that your executable references the assembly built as a result of compiling the other project. If you don't want to distribute the separate assembly with your executable the only thing you can do is to ILMERGE the assembly into your executable as a part of your deployment build process,
You can't. The way .net works is to load an additional assembly and using its meta data the classes inside that. If you are attempting to have a set of classes that you refer to by source similar to the way c++ uses header files you will have to import those files into your project.
This sounds like you're trying to statically compile a library. This is not (easily) offered by .NET without manually creating and merging assemblies.

Referencing an external .NET DLL provided by another application in C#

I have a C# project which references a DLL (call it external DLL) which comes with another application. When I build my project, due to the reference, the external DLL gets automatically added to my project output. And when I run my project it loads the external DLL from my project folder.
The other application, which the external DLL belongs to, is developed by another team and the DLL is regularly updated. I don't want to package their DLL with my project. Instead I would like to have my project load their DLL when executed -- rather than pick the DLL copy from my project's folder.
Now I know that this is possible through reflection. I know that I can do an "Assembly.Load" and pick the DLL. But because I use the types from the external DLL all through my code, I would like the code to be statically type checked.
Here's what I would like:
Be able to compile my project by referencing the external DLL and thus get static type checking.
When the project is run, the external DLL is picked up from the other application's folder and not the copy of the DLL which is in my project's output folder.
Is there any way to solve this problem? Is there some middle ground between adding a reference and using reflection?
The most immediete solution to your problem is to change the properties of the reference. There is a setting called Copy Local. Set that to false and it'll stop copying the DLL to your project's output. You can access the properties of the reference by expanding the references folder in your solution, right-clicking on the reference in question, and clicking properties to open the properties pane.
The fact that Visual Studio copies the DLL to your project's output folder at build time doesn't really matter to the .Net Framework at runtime. All that matters is that the assemblies you reference are available to the framework either in the paths it searches or in the global assembly cache.

COM Interop, isolation and excluding duplicate references

We are using a COM DLL provided by Microsoft (dsofile.dll) in a C# dll written by us (Assembly A). In order to avoid having to register the COM dll, I have switched the Isolated property on the reference to dsofile.dll to true.
This means that when we compile our dll, visual studio copies dsofile.dll, Interop.DSOfile.dll and Native manifest files to the bin folders of our solution and the application can run without the dsofile.dll being registered.
This approach was successful in a small test application.
However, in the real application, Assembly A is referenced by some of our other dlls (Assembly B and Assembly C) and the application EXE. When the native manifest file and interop dll are copied to the application's bin folder, different copies of each of the files are being used since each dll referencing our first dll creates its own copy.
This results in multiple copies of the files showing up as references in the setup project (ie dsofile.dll from the Assembly A, B and C and EXE folders, Interop.DSOFile.dll from the Assembly A, B and C and EXE folders, Native.Assembly A.manifest from the Assembly A, B and C and EXE folders) and compiler warnings ('Two or more objects have the same target location').
In addition, if the manifest and interop dll which were copied into the final folder did not come directly from the Assembly A folder (since the duplicate files overwrite one another), the application cannot successfully load the COM DLL.
I have been forced to manually exclude the duplicate copes of the files from the setup dependencies but they reappear when the solution is reloaded or rebuilt.
Can anyone help with a better method to achieve isolated deployment of the COM dll? I would also like to embed the manifests if possible but I have not been successful in doing this so far.
As an alternative I have been investigating the automation of the task of excluding the duplicate copies using EnvDTE for Visual Studio Automation but have not been able to discover how to access the Detected Dependencies nodes in a way that allows me to identify and exclude them. Accessing them with the UIHierarchyItem interface shows the name of the setup project as the name property for every file and does not have an exclude option.
Any advice would be appreciated.
I've resolved a similar problem in the past by making reference to projects instead of to the assemblies themselves. The deploy project has some problems with multiple references to assemblies that are being built in the solution.

Categories