Friday, February 04, 2011

AsmSpy: A little tool to help fix assembly version conflicts

Do you ever get these kinds of messages when you compile your project?

------ Build started: Project: Suteki.Shop.CreateDb, Configuration: Debug x86 ------
No way to resolve conflict between "System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
and "System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35". 
Choosing "System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" arbitrarily.
Consider app.config remapping of assembly "NHibernate, Culture=neutral, PublicKeyToken=aa95f207798dfdb4" 
from Version "3.0.0.2001" [] to Version "3.0.0.4000" 
[D:\Source\sutekishop\Suteki.Shop\packages\NHibernate.3.0.0.4000\lib\NHibernate.dll] to solve conflict and get rid of warning.
Consider app.config remapping of assembly "System.Web.Mvc, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
from Version "2.0.0.0" [C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 2\Assemblies\System.Web.Mvc.dll] to Version "3.0.0.0" 
[C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies\System.Web.Mvc.dll] to solve conflict and get rid of warning.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1360,9): warning MSB3247: 
Found conflicts between different versions of the same dependent assembly.
Suteki.Shop.CreateDb -> D:\Source\sutekishop\Suteki.Shop\Suteki.Shop.CreateDb\bin\Debug\Suteki.Shop.CreateDb.exe

The problem is that the build output doesn’t tell me which of my assemblies references version 2.0.0.0 of System.Web.Mvc and which references version 3.0.0.0.

If you’re writing software using lots of 3rd party assemblies like I do, it’s a constant problem. I’ve written a little bit of code that I drag around with me that outputs lists of assemblies that my assemblies reference. I’ve found it very useful for resolving these kinds of issues.

Now I’ve wrapped it up as a little console app, AsmSpy, and put it on github here:

https://github.com/mikehadlow/AsmSpy

Or you can download a zip file of the compiled tool here:

http://static.mikehadlow.com/AsmSpy.zip

How it works:
Simply run AsmSpy giving it a path to your bin directory (the folder where your project's assemblies live). E.g:

AsmSpy D:\Source\sutekishop\Suteki.Shop\Suteki.Shop\bin

It will output a list of all the assemblies referenced by your assemblies. You can look at the
list to determine where versioining conflicts occur.
 
The output looks something like this:

....
Reference: System.Runtime.Serialization
3.0.0.0 by Microsoft.ServiceModel.Samples.XmlRpc
3.0.0.0 by Microsoft.Web.Mvc
4.0.0.0 by Suteki.Shop
Reference: System.Web.Mvc
2.0.0.0 by Microsoft.Web.Mvc
3.0.0.0 by MvcContrib
3.0.0.0 by MvcContrib.FluentHtml
3.0.0.0 by Suteki.Common
2.0.0.0 by Suteki.Common
3.0.0.0 by Suteki.Shop
2.0.0.0 by Suteki.Shop
Reference: System.ServiceModel.Web
3.5.0.0 by Microsoft.Web.Mvc
Reference: System.Web.Abstractions
3.5.0.0 by Microsoft.Web.Mvc
....

You can see that System.Web.Mvc is referenced by 7 assemblies in my bin folder. Some reference
version 2.0.0.0 and some version 3.0.0.0. I can now resolve any conflicts.

45 comments:

  1. Holy smokes are you spying on me? This is exactly the problem I've been having the last couple of days. I've been using PowerShell in a similar way, but not looking at the references inside files (I was using Reflector for that), more to find out what versions of what assemblies are where in my working copy.

    Something like this:

    PS C:\data files\projects> gci -Filter Castle.Core.dll -r | %{ $_.VersionInfo } | group-object ProductVersion

    ReplyDelete
  2. Awesome, this helped me today...cheers.

    ReplyDelete
  3. Ɓukasz Podolak3:24 pm

    Thanks Mark, this has already helped me.

    ReplyDelete
  4. very nice and usefull little tool. maybe a SortedDictionary would be nice for the output. thanks!

    ReplyDelete
  5. Marco, do you mean sort the dependencies by name?

    ReplyDelete
  6. Was talking about sorting the references on namespace for easy searching, but maybe the other way around might be useful too.

    ReplyDelete
  7. Anonymous3:38 pm

    great work

    ReplyDelete
  8. Anonymous5:18 pm

    ... or you may add the following to the section of your *.config file:

    ReplyDelete
  9. Anonymous5:23 pm

    *---runtime---*
    *---assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"---*
    *---dependentAssembly---*
    *---assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /---*
    *---bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" /---*
    *---/dependentAssembly---*
    *---/assemblyBinding---*
    *---/runtime---*

    Replace *--- with a less-than and ---* with a greater-than symbol.

    ReplyDelete
  10. Anonymous4:47 am

    I'm having a terrible time getting this to work on projects that reside on a network share. Any ideas of how to get it to work? I'm getting a "Failed to load assembly: " error.

    Bernie

    ReplyDelete
  11. Thank you, this helped me.
    I run it in another way: cd to your bin, then:

    C:\alreay\at\bin\asmspy .

    ReplyDelete
  12. Brilliant! Helped me so much :)

    ReplyDelete
  13. Anonymous10:53 pm

    Thanks. Any change you can add *.EXE, in addition to *.DLL?

    ReplyDelete
  14. Hi Anonymous, done, just get the latest from GitHub.

    ReplyDelete
  15. Maybe you can add a switch for just displaying conflicts? Scanning through my output of 1500 lines takes a lot of time. =)

    ReplyDelete
  16. Stuff, pull request?

    ReplyDelete
  17. Anonymous2:28 pm

    Great tool!

    ReplyDelete
  18. Anonymous11:13 am

    This sorted my TFS build issue out. Thanks.

    ReplyDelete
  19. Thanks for sharing this... it's awesome!

    ReplyDelete
  20. Nathan1:55 pm

    This worked extra special nice. Thanks!

    ReplyDelete
  21. Anonymous4:34 pm

    Awesome tool, helped me out a ton!

    ReplyDelete
  22. So...now I can see where the problem is, but how do I fix it when the conflict seems to be at least two levels deep?

    I first noticed the problem in my project when the embedded server in VS started aborting with DotNetOpenAuth.Core conflicts. I then noticed the mapping conflict warnings, then found this page and downloaded AsmSpy. I'll just give one example from my AsmSpy output. Most references listed to mscorlib are 4.0.0.0, but one is 2.0.0.0--that's from DotNetOpenAuth.Core which also calls 4.0.0.0!

    I strongly suspect most of my problems are coming from dotnetopenauth, but I don't know what dotnetopenauth is, or how it got there, because it's not a reference that explicitly added. I'm just treading water here, and all but desperate for a resolution.

    ReplyDelete
  23. Neil Moss11:43 am

    Thank you very much. Took me straight to the root of my issue of the day.

    ReplyDelete
  24. Thanks for that very useful tool. It showed me exactly where my problem was.

    ReplyDelete
  25. this is totally awesome, get to go home now :)

    ReplyDelete
  26. Excellent! I'm not sure how I've missed this tool before, as it's priceless. I've been having some reference problems in a WP7 app and the Visual Studio's info outputs haven't been useful. With this tool it took only few minutes to figure out the problem!

    Thanks!

    ReplyDelete
  27. Yes, a terrific tool. Thanks for contribution

    ReplyDelete
  28. Anonymous5:05 pm

    Very useful, thanks.

    ReplyDelete
  29. Anonymous6:37 pm

    Thank you, thank you, thank you. This is a godsend!

    ReplyDelete
  30. Anonymous7:45 pm

    Thank you for this! Day three of troubleshooting solved in 10 MINUTES. Love it.

    ReplyDelete
  31. Great tool, thanks!

    ReplyDelete
  32. Adding to the long list of thank you's

    ReplyDelete
  33. This helped me too, thank you very much!

    ReplyDelete
  34. Anonymous3:52 am

    Thanks!!

    ReplyDelete
  35. You sir, are a f*cking hero.

    ReplyDelete
  36. Anonymous11:35 pm

    Great tool, thanks!

    ReplyDelete
  37. THANK YOU! This tool helped me finally solve an issue that has been causing me a big headache.

    ReplyDelete
  38. Very interesting but i cannot understand how other can run it.

    I tried with differents paths and only received the messages "Usage:
    AsmSpy
    E.g.
    AsmSpy C:\Source\My.Solution\My.Project\bin\Debug"

    ReplyDelete
  39. Randy Dellinger8:06 pm

    It didn't work if I gave the full path as the argument, so instead I copied AsmSpy to my project folder and ran:

    AsmSpy .\bin\Debug

    ReplyDelete
  40. Can you update the link to the zip on this site to be the same as the one on github? The one here links to https://github.com/mikehadlow/AsmSpy and doesn't support any options, while the link on github points to http://static.mikehadlow.com/AsmSpy.zip and does support options.

    ReplyDelete
  41. Thanks for pointing that out Steve. Link updated!

    ReplyDelete
  42. Thanks! Great tool btw!

    ReplyDelete
  43. Thank you so much for this tool. I could fix the always annoying MSB3277 warning "Found conflicts between different versions of the same dependent assembly" within seconds.

    ReplyDelete

Note: only a member of this blog may post a comment.