Referencing 2 different versions of log4net in the same solution
Asked Answered
D

3

83

I'm using NHibernate 2.1.2.400 that is referencing log4net 1.2.10.0. In the same project, I also use the simply accounting SDK, sadly it is still using log4net 1.2.9.0.

So I can get NHibernate to work if I reference log4net 1.2.10.0 but the simplySDK don't work. And vice versa...

I'm guessing most of the problems come from the fact that log4net has changed its assembly key. I tried using a binding redirection without success: the 2 DLLs do not have the same key.

I'm considering recompiling NHibernate to use log4net 1.2.9.0 but it seems like the wrong thing to do and my feeling is that Simply Accounting won't be updating their SDK to use log4net 1.2.10.0 anytime soon.

What is the best way to handle this? Is it possible to resolve at all?

Delitescent answered 1/7, 2010 at 14:51 Comment(3)
I have a very similar question at #1745043 I resorted to recompilation. I guess this is the advent of dll-hell v2.0.Unsling
while checking your question I found https://mcmap.net/q/212795/-using-different-versions-of-the-same-assembly-in-the-same-folder#2461746 that fixed my problem.Delitescent
Great! I had been wondering about making the CLR look in different locations and the href attribute seems to do the trick. Thanks for pointing that out!Unsling
D
155

I found the solution by using this answer to a similar question

You create 2 folders in your project one for each version of log4net. Place each log4net.dll in its corresponding folder by adding an the file to the solution (not with add reference). You can set the copy to output directory property to copy always so that it is automatically copied to the output folder when you build.

Then you modifiy the app.config file by adding something like this:

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="681549d62126b7b8" />
        <codeBase version="1.2.9.0" href="log4netv1.2.9.0\log4net.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" />
        <codeBase version="1.2.10.0" href="log4netv1.2.10.0\log4net.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" />
        <codeBase version="1.2.11.0" href="log4net.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

you can get the public key token of an assembly by using sn -T [assemblyName]

Delitescent answered 2/7, 2010 at 3:11 Comment(15)
This seems to work for me as well. I removed log4net from my References list for the project where the conflict was occuring. Also, since log4net.dll is not in my bin folders, my href paths looked more like "..\..\..\..\Lib\NHibernate-2.0.1.GA\log4net.dll"--just a relative path to where log4net will be on every dev's machine with our build system.Choreographer
I'm not sure I get this: how do you not get compiling errors if log4net is not referenced?Eisenstein
@Eisenstein I think it may just be a dependency of a reference. That's why it may compile without the reference and still work at runtime.Shea
This is awesome, it would fix other cases where a simple binding redirect would break things due to API changes too!Hydromagnetics
@guidupy you can reference the log4net your code uses, but turn off the copyLocal in the properties.Statutable
Can any PC configurations cause this to not work? I find it's working fine for me, but not when deployed to my customer's pc.Jed
This is the best way after trying so many suggesstion and speand afew hours.Now it works perfectly.ThanksTruesdale
great, works like a charm, with only one modification, for the project to build, I added the correct reference but set its property Copy Local = FalseLevitt
also I for the dlls included in the project, set properties to 'Copy if newer'Levitt
How do you handle the config section declaration in this case? Does it matter which assembly you map it to? It won't log if you don't specify the full type in the section declaration; but you can only have one section declaration.Broomfield
Excellent solution, but there is a trick. Due to a bug, codeBase in web.config may not take unless there is also bindingRedirect present!Kobe
And it's a damning indictment of Apache's choices here that we're still wasting time attempting to solve this problem. For anyone who's coming to this problem again -- note that this fix will only work for projects that will actually use an app.config, not for class libraries, for example.Plectron
for future readers (a hint I found from another answer, but prudent to post here)... for web-applications (asp.net), the reference has a tweak: <codeBase version="1.0.0.0" href="bin\folder\namedll.dll" />Zee
Please note that if you want to get the assembly key token, make sure to pass capital T to the sn tool, otherwise it will fail: sn -T "assembly full path"Pendley
How are the appenders setup when using this solution. Can the logs from codebase using different log4net versions write to the same file?Flong
R
7

You can add an exclusion to the registry. Just add these keys:

HKEY_LOCAL_MACHINE\Software\Microsoft\StrongName\Verification\log4net,681549d62126b7b8
HKEY_LOCAL_MACHINE\Software\Microsoft\StrongName\Verification\log4net,1b44e1d426115821
HKEY_LOCAL_MACHINE\Software\Microsoft\StrongName\Verification\log4net,669e0ddf0bb1aa2a

This will make the .net runtime skip validation for the listed assemblies. In theory this is a security issue, but since the private key is out in the open anyway, there's hardly any impact.

Runnymede answered 4/2, 2016 at 9:25 Comment(2)
As you said, this is a security issue. Also, this woud imply that you must make those change on every workstation that runs the software. In a complex enterprise network those kind of things adds up to make a huge mess. I'd rather avoid it as much as possible. The others solutions are self-contained and portable.Delitescent
As i said, because the private keys are publicly available anyway, there is no real security issue at all. Especially in an enterprise network it would be more easy to configure a single Group Policy Object, than to configure this for every LOB application in use. You can configure it once at a domain level and never have to think about it again.Runnymede
B
3

If binding redirection doesn't work and the simply accounting SDK is closed source, a possible solution is recompiling NHibernate to use log4net 1.2.9.0.

Bk answered 1/7, 2010 at 17:28 Comment(1)
That would work, but having to build a special version of nhibernate would be harder to support down the line... thanks.Delitescent

© 2022 - 2024 — McMap. All rights reserved.