使用nuget时,我该如何解决dll hell?

时间:2017-06-19 05:19:14

标签: c# .net dll dependencies nuget

在C#项目中使用nuget时,有一个地狱难题。 例如,如果您看到如下图所示的内容,

- MyNugetTest
    - Newtonsoft.Json : v10.0.3
    - ...
    - MyLib
        - Newtonsoft.Json : v5.0.1
        - ...

结果如下。

PS C:\temp\MyNugetTest> ls .\MyNugetTest\bin\ -Recurse | select FullName
FullName
--------
C:\temp\MyNugetTest\MyNugetTest\bin\Debug
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\MyLib.dll
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\MyLib.pdb
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\MyNugetTest.exe
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\MyNugetTest.exe.config
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\MyNugetTest.pdb
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\Newtonsoft.Json.dll
C:\temp\MyNugetTest\MyNugetTest\bin\Debug\Newtonsoft.Json.xml

PS C:\temp\MyNugetTest> [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\temp\MyNugetTest\MyNugetTest\bin\Debug\Newtonsoft.Json.dll").FileVersion
10.0.3.21018

MyNugetTest总是在以后构​​建,会覆盖Newtonsoft.Json.dll文件,因此版本确定为v10.0.3。

如果我手动将文件名更改为Newtonsoft.Json.v5.0.1.dll,则此问题将得到解决。 有没有办法用nuget或visual studio工具自动修复它?

2 个答案:

答案 0 :(得分:3)

@EmrahSüngü回答,

作为各种测试的结果,为了解决dll地狱问题,分配全球GAC所需的dll似乎是个好主意。 如果我开发本地应用程序,则很麻烦,因为GAC注册过程包含在安装程序中。 因此,最好只在出现问题时执行GAC安装,而不是在GAC安装时抢占所有依赖项。

以下是注册此GAC后运行应用程序的结果。




执行目录和GAC中都不存在Newtonsoft.json.dll,并且发生执行错误。

PS C:\temp\MyNugetTest> .\MyNugetTest\bin\Debug\MyNugetTest.exe

처리되지 않은 예외: System.IO.FileNotFoundException: 파일이나 어셈블리 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' 또는 여기에 종속되어 있는 파일이나 어셈
블리 중 하나를 로드할 수 없습니다. 지정된 파일을 찾을 수 없습니다.
   위치: MyNugetTest.Program.Main(String[] args)




检查nuget包目录中需要部署的所有dll。

PS C:\temp\MyNugetTest> ls .\packages\*.dll -Recurse | select FullName
FullName
--------
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\net20\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\net35\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\net40\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.0\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\portable-net40+sl5+win8+wp8+wpa81\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.10.0.3\lib\portable-net45+win8+wp8+wpa81\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\net20\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\net35\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\net40\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\net45\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\netcore45\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\portable-net40+sl4+wp7+win8\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\portable-net45+wp80+win8\Newtonsoft.Json.dll
C:\temp\MyNugetTest\packages\Newtonsoft.Json.5.0.1\lib\wp80\Newtonsoft.Json.dll




在GAC中安装/注册所有dll

PS C:\temp\MyNugetTest> ls .\packages\*.dll -Recurse | foreach { gacutil -i $_.FullName }
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

어셈블리를 캐시에 추가했습니다.




确保您已正确安装/注册GAC

PS C:\temp\MyNugetTest> ls C:\Windows\assembly\GAC_MSIL\Newtonsoft.Json\*.dll -Recurse | select FullName

FullName
--------
C:\Windows\assembly\GAC_MSIL\Newtonsoft.Json\10.0.0.0__30ad4fe6b2a6aeed\Newtonsoft.Json.dll
C:\Windows\assembly\GAC_MSIL\Newtonsoft.Json\4.5.0.0__30ad4fe6b2a6aeed\Newtonsoft.Json.dll




确保我的应用程序再次运行良好

(哦!它运行良好!)

PS C:\temp\MyNugetTest> .\MyNugetTest\bin\Debug\MyNugetTest.exe
objStr : {"hello":"world","main":"function"}
c1.ObjStr : {"hello":"world"}




从GAC中删除/取消注册Newtonsoft.Json。

(这一步很危险,大部分时间你都不需要它。 但我会将其添加进行测试。)

PS C:\temp\MyNugetTest> gacutil -u Newtonsoft.Json
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.


어셈블리: Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL
제거됨: Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL

어셈블리: Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL
제거됨: Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL
제거한 어셈블리 수 = 2
실패한 횟수 = 0




我运行应用程序时也失败了。

PS C:\temp\MyNugetTest> .\MyNugetTest\bin\Debug\MyNugetTest.exe

처리되지 않은 예외: System.IO.FileNotFoundException: 파일이나 어셈블리 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' 또는 여기에 종속되어 있는 파일이나 어셈
블리 중 하나를 로드할 수 없습니다. 지정된 파일을 찾을 수 없습니다.
   위치: MyNugetTest.Program.Main(String[] args)

答案 1 :(得分:2)

您可以让每个项目引用同一dll的特定版本。我有两种方式可以想到:

1)将两个版本的dll放在GAC中。然后,在引用时设置Copy Local = false和Specific Version = true。

2)使用您的配置文件和assembly binding directives

但是,我们拥有GAC的主要原因之一是解决这个问题。所以我建议利用它。