我该如何解决log4net不断更改publickeytoken的问题?

102
我们有一个asp.net 4.0项目,使用了几个依赖于log4net版本1.2.10.0的框架。今天我试图包含一个依赖于log4net版本1.2.11.0的新框架,但是自此以后就一直卡住了: log4net 1.2.10.0的publickeytoken = 1b44e1d426115821 log4net 1.2.11.0的publickeytoken = 669e0ddf0bb1aa2a
由于这些不同,我不能使用程序集重定向(使所有框架使用相同版本的log4net)或代码库(仅使新框架使用版本1.2.11.0)通过web.config中的运行时元素。
我的选择是什么?
(为什么log4net在不同版本之间不断更改publickeytokens呢?据我了解,丢失密钥是1.2.9.0和1.2.10.0版本之间切换的原因,他们是否再次丢失了密钥?如果他们需要,我会自愿提供我的Dropbox来保存它...)
编辑:好吧,log4net的人显然认为发布两个密钥是个好主意,但这意味着您使用的每个框架都需要同意他们喜欢哪一个版本,否则这些框架无法在同一个应用程序域中并存。我是唯一发现这个想法很可怕的人吗?如果每个人都这样做,那么一切都会崩溃,对吧?
编辑2:正如我所说,我没有在我的业务代码中使用log4net,但我使用了几个依赖于1.2.10.0版本的框架,当我尝试使用一个依赖于1.2.11.0版本(新密钥)的新框架时,问题就出现了,因此Stefans的答案并不适用,因为新框架将期望新密钥,而不是旧的密钥。

1
在我看来,Apache 的第一个错误是提供使用新密钥签名的二进制文件:新密钥仅适用于已打补丁/增强的开源版本,不应直接使用。第二个错误是你所说的框架只发布了带有新 log4net 签名的版本:应该存在一个带有旧签名的版本。 - JoeBilly
6
实际上,您正在查看第三个版本:SAP的天才重新编译了自己的强名称作为Crystal Reports for Visual Studio软件包的一部分,并且更糟糕的是,他们将其放在GAC中,这会使得跨不同机器的依赖关系变得非常麻烦。 - Jeremy Holovacs
6个回答

65

这是我如何通过版本1.2.11.0使事情正常工作的方式。

  1. 咒骂Apache首先更改密钥:)
  2. 下载使用旧密钥签名的版本1.2.11.0。
  3. 通过删除任何对log4net(新密钥)的直接引用并将其替换为使用旧密钥签名的程序集的引用,解决自己的代码问题。
  4. 如果您有任何相关的程序集,请在您的web/app.config中包含此段内容进行处理。
   <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-1.2.10.0"
                                 newVersion="1.2.11.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>

9
由于无法对使用不同公钥的程序集执行绑定重定向,因此需要下载由旧公钥签名的版本。 - David Christiansen
2
这似乎是由于1.2.11.0中的破坏性更改而失败:http://netpl.blogspot.com/2012/03/pathetic-breaking-change-between.html - sydneyos
很遗憾,除了降级到1.2.10版本之外,目前没有其他解决方案。(或者重新编译您所使用的每个依赖程序集) - bk0
1
将1.2.10程序集放在另一个目录中,并使用以下配置: '<dependentAssembly> <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-1.2.9.0" newVersion="1.2.10.0"/> <codeBase version="1.2.10.0" href="Resources\log4net-oldkey\log4net.dll" /> </dependentAssembly>' - Agile Jedi
@AgileJedi - 我已经尝试了你提到的帖子,我可以确认这对我有效。 - ctrlplusb
显示剩余4条评论

30

我正在使用通过NuGet下载的log4net最新版本。然而,我正在使用的一个库需要旧版本。我的问题引导了我来到这个问题。

其他答案的问题在于它们为所有绑定使用相同的dll版本。我想在其他所有地方使用新版本的特性,但保留对旧版本的依赖。

为了能够做到这一点,您需要执行以下操作:

  1. 首先通过下载旧版本(版本号为1.2.11.0)。
  2. 将下载的二进制文件重命名为log4net.1.2.10.dll,并将其包含在启动项目中,构建操作设置为None且选择“如果较新则复制”。 enter image description here
  3. 告诉.NET可以在哪里找到旧版本:

App.config

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" />
            <codeBase version="1.2.10.0" href="log4net.1.2.10.dll" />
        </dependentAssembly>
    </assemblyBinding>
</runtime>

href 属性标识旧版本所在位置,因此所有对 log4net 的其他请求将指向新版本。


4
这是一个很好的解决方案,因为它允许你同时维护针对引用任一版本的库的两个版本。 - SouthShoreAK
2
谢谢!这个救了我。我不得不将“复制到输出目录”更改为“不复制”,但除此之外,它的工作非常好! - Daniel Hedenström

3
您可以下载一个使用旧密钥签名的log4net 1.2.11.0版本。更换新密钥的原因在他们的常见问题解答中有解释:http://logging.apache.org/log4net/release/faq.html#two-snks (基本上,新密钥是公开可用的,由于某种原因,他们不想在分发中包含旧密钥。但我不清楚为什么他们不只是公开旧密钥)。)

10
但是当我使用一个绑定了新密钥的第三方库时,我仍然会陷入困境(对吗?)。使用新的log4net不是我的选择,而是第三方框架。随着越来越多的框架开始使用具有新密钥的log4net,我看不出这些东西如何不会在每个人的面前爆炸。 - AndreasKnudsen
很不幸,那是正确的。我想你需要考虑不让所有组件使用相同版本的log4net... - Stefan Egli
1
我该如何实现这个?在 .net 中有没有处理这个问题的机制? - AndreasKnudsen
是的,有:https://dev59.com/3XA75IYBdhLWcg3wrrNS - ms007

1

不知道是否适用于您的特定情况,但您可以重新编译其中一个框架,以便它们使用具有相同公钥的log4net。在我的情况下,FluentNHibernate使用log4net 1.2.10,而Combres使用具有新密钥的log4net 1.2.11。我下载了使用旧密钥签名的log4net 1.2.11,并将Combress重新编译为它。之后添加了从1.2.10到1.2.11的程序集绑定重定向,然后它开始工作。


0

我尝试访问上面提供的链接,但似乎Apache网站上的所有链接都无法使用。然后我采取了以下措施来解决这个问题:

从您的Visual Studio中,使用Nuget下载并安装最新版本的log4net(1.2.13.0)。 NuGet软件包管理器将自动下载并升级所有log4net(1.2.11.0)到最新版本。


0
这并非在所有情况下都适用,但由于使用log4net的项目是开源的,我下载了源代码,用我正在使用的版本替换了冲突的log4net版本,并重新构建了该项目。在我的案例中,它是Topshelf,因此我现在有一个使用与我相同版本的log4net构建的Topshelf程序集版本,现在我可以引用两者而无需担心问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接