Runtime loading of private assemblies in a subdirectory - c#

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.

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.

Load assembly from a path without copying it to bin folder

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 !

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.

.Net Publisher Policy: Both Assemblies required to be in the GAC?

I have created a publisher policy assembly following the post How to: Create a Publisher Policy. The policy redirects assemblies from the version 1.0.0.0 to the version 2.0.0.0.
This does work for me as long as the old assembly (v1.0.0.0) is located on the server (in the GAC). Is it possible to remove the old assembly version from the server?
The configuration I used:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Assembly.Name"
publicKeyToken="d24d3f23b4455982"
culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0"
newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Shame on me. I did a mess with the assembly versions. So the answer is: Yes, it works without the legacy assembly.

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