Load assembly from a path without copying it to bin folder - c#

I have a simple c# application and I would like to reference an assembly from C:\..\..myassembly.dll without copying the thing to bin folder.
I there a way to change how is assembly being referenced/loaded?
Edit: the assembly is not in gac

Actually it is possible during runtime by using <codeBase> tag in your configuration:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MyAssembly2" culture="neutral" publicKeyToken="307041694a995978"/>
<codeBase version="1.0.1524.23149" href="FILE://C:/Myassemblies/MyAssembly2.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
You can refer to the MSDN to get more specific info. The downside of this solution is that you have to manually specify assembly version.

Multiple solutions to your problem.
To avoid copying library to output folder set Copy Local to false by selecting .dll property.
Option 1:
Include below section in your configuration file and let allow runtime to load from location you specified.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MyAssembly" publicKeyToken="2d65620afb84f19d" />
<codeBase version="1.0.0.0" href="C:\..\..myassembly.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Option 2:
Well known option, use reflection to load your assembly.
Assembly.Load(#"C:\..\..myassembly.dll")
Hope this helps !

Related

How to chage default directory of .dlls creating after built with runtime and probing?

I want to move all .dlls to "lib" folder after building my application. Default program creates them in directory:
bin\Debug\netcoreapp2.2
And this is directory where I want to place my .dlls:
bin\Debug\netcoreapp2.2\lib
I create script which moves my .dlls to this folder and put it in post-built event. It works correctly.
Next, I add runtime to my app.config file like I saw in many tutorials and articles on stackoverflow.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib"/>
</assemblyBinding>
</runtime>
But, after building and starting my program, console says:
The application to execute does not exist:
app\bin\Debug\netcoreapp2.2\myDLL.dll
I want to know what's wrong with my application? How can I change the directory in which program is looking for .dlls?
I guess what you need is the codebase element in the configuration.
From documentation, If the assembly has a strong name, the codebase setting can be anywhere on the local intranet or the Internet. If the assembly is a private assembly, the codebase setting must be a path relative to the application's directory.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="myAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="neutral" />
<codeBase version="2.0.0.0"
href="http://www.litwareinc.com/myAssembly.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Hope this helps.

Runtime loading of private assemblies in a subdirectory

I have been trying to load a private assembly which is located in a subdirectory under the application base directory. I have an assembly named Sparrow.dll which is located under plugins directory (which is under application base dir also). Whenever I call Assembly.Load("Sparrow") I get a System.IO.FileNotFoundException.
I used app.exe.config with tag and it worked with a strong named version of the same assembly with the line below;
Assembly assem = Assembly.Load("Sparrow");
However, it does not work when I changed the assembly in to a weak assembly.
The content of the config file is below;
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly name="Sparrow, Culture=neutral, PublicKeyToken=xxxxxx">
<codeBase version="1.0.1.1" href="plugins/Sparrow.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
I read many things, but I am not sure whether using tag for locating weak assemblies is a good practice or not.
You can use the probing element for that purpose:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="plugins" />
</assemblyBinding>
</runtime>
</configuration>
That element means that the plugins subfolder will be searched for assemblies.
Note however, that only directories that are on a descendent path of the application directory can be specified in that way.
The configuration file in your question has a mistake. According to documentation, the XML configuration should look like:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Sparrow"
publicKeyToken="null"
culture="neutral" />
<codeBase version="1.0.1.1" href="plugins/Sparrow.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
However, I think that using the probing element would be a better choice in your case.

Why assemblyBinding is ignored?

I have an IIS Application defined under the "Default Web Site" for which I would like to use a common assembly defined in another directory than /bin. I added a section to the web.config of the IIS Application with the location of the common assembly. However, it appears that that the assemblyBinding is ignored. Why is it ignored?
<runtime>
<probing privatePath="C:\Program Files\MyProduct\Bin\" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MyProduct.Security" publicKeyToken="XXXXXXXXXXXXXXXXX" culture="neutral" />
<codeBase version="1.0.0.0" href="file:///c:\program files\myproduct\bin\MyProduct.Security.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
From MSDN:
If the assembly has a strong name, the codebase setting can be
anywhere on the local intranet or the Internet. If the assembly is a
private assembly, the codebase setting must be a path relative to the
application's directory.

Another assembly referencing the old dll

I have 2 assemblies lets call them A and B. I've assigned strong names to them and now the problem arises that assembly B is looking for the old version of assembly A.
**EDIT2: If I delete AssemblyB the problem persists so it might just be VS2008 looking for the old version? Also via fusionlog I see the following warning: wrn application configuration file binding redirects disallowed. Does this have anything to do with it? **
I get multiple errors of the same kind, here's one snippet:
You must add a reference to assembly 'AssemblyA, Version=1.2.4737.25316, Culture=neutral, PublicKeyToken=null'.
The strong named AssemblyA inside the project shows these properties:
Inside app.config I've placed this piece of code:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="AssemblyA" culture="neutral"
publicKeyToken="a22e30ac6a0edfc0"/>
<bindingRedirect oldVersion="1.2.4737.25316" newVersion="1.3.0.19440"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
But this does not work. I have access to the source of both assemblies.
EDIT: If I delete the strong named and add the old (weak named) dll to the project it will give an error asking about the strong named version
You must add a reference to assembly 'AssemblyA, Version=1.3.0.19440, Culture=neutral, PublicKeyToken=a22e30ac6a0edfc0'.
What's happening here?
Some DLL's still referred to the old (weak named) version of other DLL's. Luckily the assemblies came with the source so I had to recompile everything including a key.
After that another error came up along the lines of "The located assembly's manifest definition does not match the assembly reference"
To fix this I added the following in the app.config.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<publisherPolicy apply="no" />
<assemblyIdentity name="Assemblyname" culture="neutral" publicKeyToken="3a5628535d42dbed"/>
<bindingRedirect oldVersion="1.3.0.15233" newVersion="1.3.0.40647" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Downgrade (use a lower-versioned library) with a binding redirect

I'm using an older version of NHibernate (v3.0.0.1001) and I'm stuck to it because the new LINQ provider breaks quite a few of my queries (something I'll be trying to fix later). I want to update a library that uses NHibernate v3.1.0.4000.
I've tried adding a binding redirect in the App.config:
<?xml version="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.1.0.4000" newVersion="3.0.0.1001"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
But when I compile, I get:
error CS1705: Assembly 'My3rdPartyDll, Version=0.5.0.170, Culture=neutral, PublicKeyToken=null' uses 'NHibernate, Version=3.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4' which has a higher version than referenced assembly 'NHibernate, Version=3.0.0.1001, Culture=neutral, PublicKeyToken=aa95f207798dfdb4'
Is it possible to use a binding redirect to point to a downgrade?
You can use the probing Element to specify a specific folder to find the dll, and then you can just past the dll into that folder.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Assemblies"/>
</assemblyBinding>
</runtime>
You can aslo specify a specific assembly to use which is what I think you are looking for.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WorkflowLibrary1" publicKeyToken="8afb6d596a769080" />
<codeBase version="1.0.0.0" href="Version_1_0_0_0/WorkflowLibrary1.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
This Link goes into more details about this.

Categories