como faço para contornar o log4net, mudando publickeytoken

99

Temos um projeto asp.net 4.0 que usa algumas estruturas que dependem do log4net versão 1.2.10.0. Hoje eu tentei incluir um novo framework que depende do log4net versão 1.2.11.0, estive preso desde então:

log4net 1.2.10.0 has publickeytoken = 1b44e1d426115821

log4net 1.2.11.0 has publickeytoken = 669e0ddf0bb1aa2a

Como são diferentes, não posso usar redirecionamentos de montagem (para fazer com que todos os frameworks usem a mesma versão do log4net) ou codebase (para que apenas o novo framework use a versão 1.2.11.0) por meio do elemento runtime em web.config.

Quais são minhas opções aqui?

(e por que o bip é que o log4net fica mudando publickeytokens entre as versões, pelo que entendi uma chave perdida foi a razão para a troca entre a versão 1.2.9.0 e 1.2.10.0, eles perderam a chave mais uma vez? para mantê-lo seguro, se necessário ...)

Edit: Ok, então os caras do log4net aparentemente tiveram a ideia de que lançar com duas chaves era uma boa ideia, mas isso significa que cada framework que você faz uso precisa concordar em qual dos dois sabores eles preferem, ou esses frameworks não funcionam lado a lado lado a lado no mesmo appdomain. Sou o único a achar esta ideia horrível? se todo mundo fizesse isso, tudo iria quebrar, certo?

Edit2: Como afirmei, não estou usando log4net em meu código de negócios, mas uso vários frameworks que dependem de 1.2.10.0, e o problema surgiu quando tentei usar um novo framework que dependia de 1.2.11.0 (nova chave ), então a resposta de Stefans não se aplica, porque a nova estrutura espera a nova chave, não a antiga

AndreasKnudsen
fonte
1
IMHO, o primeiro erro do apache aqui é fornecer os binários assinados com a nova chave: a nova chave é destinada à versão de código aberto corrigida / aprimorada e não deve ser usada como está. O segundo erro é que a estrutura da qual você está falando foi lançada apenas com a nova assinatura log4net: deve existir uma versão com a assinatura antiga.
JoeBilly
6
Na verdade, você está olhando para o terceiro tipo: aquele que os gênios da SAP recompilaram com seu próprio nome forte, como parte do pacote Crystal Reports para Visual Studio, e para piorar as coisas, eles o colaram no GAC, o que fará suas dependências entre máquinas um pesadelo.
Jeremy Holovacs

Respostas:

65

Foi assim que fiz as coisas funcionarem com a versão 1.2.11.0.

  1. Amaldiçoe o Apache por mudar a chave em primeiro lugar :)
  2. Baixe a versão 1.2.11.0 assinada com a chave antiga.
  3. Classifique seu próprio código removendo todas as referências diretas a log4net (nova chave) e substitua por uma referência ao assembly assinado com a chave antiga.
  4. Classifique quaisquer assemblies dependentes que você possa ter, incluindo este segmento em seu 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>
David Christiansen
fonte
9
Baixar a versão assinada com a chave pública antiga é necessário, pois infelizmente não é possível realizar um redirecionamento de ligação para um assembly com uma chave pública diferente.
David Christiansen
2
Isso parece falhar devido a uma alteração significativa em 1.2.11.0: netpl.blogspot.com/2012/03/…
sydneyos
Alguém encontrou uma solução para os problemas descritos no link citado por @sydneyos que causa a seguinte exceção:Method not found: 'Void log4net.Config.BasicConfigurator.Configure()'
Neo
Infelizmente, não há outra solução a não ser fazer o downgrade para 1.2.10. (ou recompilar cada assembly dependente que você usar).
bk0
1
Coloque o assembly 1.2.10 em um diretório diferente e use esta configuração: '<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
27

Estou usando a versão mais recente do log4net, que baixei por meio do nuget. No entanto, uma das bibliotecas que estou usando requer a versão antiga. Meus problemas me levaram a esta pergunta.

O problema com as outras respostas é que eles estão usando a mesma versão dll para todas as ligações. Quero usar os recursos da nova versão para todo o resto, menos para a dependência legada.

Para fazer isso, você precisa fazer o seguinte:

  1. Comece baixando a versão antiga (versão 1.2.11.0).
  2. Renomeie o binário baixado para log4net.1.2.10.dll. Inclua-o em seu projeto de inicialização com a ação Build definida como Nonee "Copiar se for mais recente" insira a descrição da imagem aqui
  3. Informe ao .NET onde ele pode encontrar a versão antiga:

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>

Os hrefatributos identificam onde está a versão antiga. Portanto, todas as outras solicitações para log4net apontarão para a nova versão.

jgauffin
fonte
4
Esta é uma ótima solução porque permite que você mantenha as duas versões das bibliotecas que fazem referência.
SouthShoreAK
2
OBRIGADO! Isso me salvou. Eu tive que mudar o "Copiar para diretório de saída" para "Não copiar", mas por outro lado funcionou perfeitamente!
Daniel Hedenström
3

Você pode baixar uma versão do log4net 1.2.11.0 que é assinada com a chave antiga. O motivo da mudança para uma nova chave é explicado em seu FAQ:

http://logging.apache.org/log4net/release/faq.html#two-snks

(Basicamente, a nova chave está disponível publicamente e, por algum motivo, eles não queriam incluir a chave antiga na distribuição. Não está claro para mim por que eles não apenas disponibilizaram a chave antiga publicamente)

Stefan Egli
fonte
10
Mas quando eu uso uma biblioteca de terceiros que está vinculada à nova chave, ainda estou preso (certo?). Não é minha escolha usar o novo log4net, é a estrutura de terceiros. Não consigo ver como isso não vai explodir na cara de todos à medida que mais e mais frameworks começam a usar log4net com a nova chave
AndreasKnudsen
Infelizmente, isso está correto. Acho que você precisa considerar não ter todos os componentes usando a mesma versão do log4net ...
Stefan Egli
1
.... e como eu faria para fazer isso? Existe algum mecanismo em .net para lidar com esse problema?
AndreasKnudsen
1

Não sei se é adequado para o seu caso particular ou não, mas você pode recompilar um dos frameworks, então eles usarão log4net com a mesma chave pública. No meu caso foi FluentNHibernate que usa log4net 1.2.10 e Combres com log4net 1.2.11 com nova chave. Eu baixei o log4net 1.2.11 assinado com a chave antiga e recompilei o Combress com ela. Depois disso, a associação de assembly adicionada redireciona de 1.2.10 para 1.2.11 e começa a funcionar.

alex
fonte
0

Isso não funcionará necessariamente em todos os casos, mas como o projeto que estava usando log4net era OSS, baixei o código-fonte, substituí a versão conflitante do log4net pela versão que estava usando e reconstruí o projeto. No meu caso, era o Topshelf, então agora tenho uma versão do conjunto Topshelf que foi construída com a mesma versão do log4net que estou usando e agora posso fazer referência a ambos sem problemas.

Mark J Miller
fonte
0

Tentei acessar os links fornecidos acima, mas parece que todos os links no site do Apache não estão funcionando. Então, fiz o seguinte para resolver o problema:

No Visual Studio, use o Nuget para baixar e instalar a versão mais recente do log4net (1.2.13.0). O gerenciador de pacotes NuGet baixará e atualizará automaticamente todo o log4net (1.2.11.0) para a versão mais recente.

George Huang
fonte