1

When using nuget in a C # project, there is a dll hell problem. For example, if you see something like the picture below,

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

The results are as follows.

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 which is always built later, overwrites the Newtonsoft.Json.dll file, so the version is determined to v10.0.3.

If I manually change the file name to Newtonsoft.Json.v5.0.1.dll, this problem will be solved. Is there any way to fix it automatically with nuget or visual studio tools?

Hyundong Hwang
  • 711
  • 1
  • 8
  • 19

2 Answers2

3

As @Emrah Süngü answers,

As a result of various tests, it seems to be a good idea to distribute the dlls required by the GAC globally in order to solve the dll hell problem. If I develop a local application, it is cumbersome because the GAC registration process is included in the installation program. Therefore, it is better to perform GAC installation only when problems occur, rather than preempting all dependencies with GAC installation.

Below is the result of running the application after registering this GAC.




Newtonsoft.json.dll is not existed in both the execution directory and GAC, and execution error occurs.

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)



Check all the dlls that need to be deployed in the nuget packages directory.

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



Install / register all dlls in the GAC

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.

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



Ensure that you are properly installed / registered with the 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



Make sure my application runs well again

(Oh! It runs well!)

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



Remove / unregister Newtonsoft.Json from GAC.

(This step is dangerous and you will not need it most of the time. But I'll add it for testing.)

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



It also fails when I run my application.

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)
Community
  • 1
  • 1
Hyundong Hwang
  • 711
  • 1
  • 8
  • 19
2

You can have each project reference a specific version of the same dll. There are two ways I can think of:

1) Put both versions of the dll in the GAC. Then, when referencing set the Copy Local = false and Specific Version = true.

2) Use your config file and assembly binding directives.

However, One of the main reasons we have GAC is to solve this problem. So I would recommend taking advantage of it.

Hasan Emrah Süngü
  • 3,488
  • 1
  • 15
  • 33
  • 1
    While it was true that GAC was supposed to be used to solve this problem, it is now viewed as an antiquated way to solve it (NuGet being the more modern alternative). The fact that there is [no GAC equivalent in .NET Core](https://stackoverflow.com/q/35538093/181087) should be motivation enough not to use the GAC. – NightOwl888 Jun 19 '17 at 06:33
  • 1
    @NightOwl888 I think this problem should be solved through nuget if possible. But is it possible that nuget does not have the same functionality as the version directory like GAC? Like bin\debug\packages\Newtonsoft.Json.5.0.1\lib\net45\Newtonsoft.Json.dll, it will be distributed in the form of nuget, and it would be nice if it becomes a dynamic reference. – Hyundong Hwang Jun 19 '17 at 06:43
  • 1
    Not exactly. NuGet chooses one version or the other and automatically generates assembly binding redirects (as in nirmal's answer). Older versions of NuGet always choose the lowest common version. More recent versions now have a warning in the install log that tells you a version conflict was detected and which version was installed to resolve it. You should be able to lookup the algorithm used now that it is open source. – NightOwl888 Jun 19 '17 at 06:51
  • @NightOwl888, Thanks for the extra info!. I still have not touched .Net Core so I did not know there was no equivalent of GAC. I need to study more :) – Hasan Emrah Süngü Jun 19 '17 at 07:11