locked
VS2010 Problem with Nuget references in projects shared across multiple solutions

    Question

  • We started using Nuget to download/reference Castle Windsor 3.1 assembly in projects p1, p2, p3, p4, p5 where each project is shared across solutions s1, s2, s3, s4, s5.   Each time we open solutions s2-s5 and try to build we get build errors because the castle windsor assembly can't be resolved (even though it just resolved / built just fine in solution s1).  We fix the issue in each solution by removing the nuget assembly references for Castle Windsor and re-add them (using Nuget) for each project that uses windsor.  This is very painful and time consuming.  Note, we have the Package Restore option enabled for downloading missing packaged during build on all solutions.  This doesn't seem to help.

    Anyone else run into anything like this?

    Nuget 2.1.31002.9028

    Visual Studio 10.0.40219.1 SP1

    VS2010 

    • Edited by scott_m Wednesday, October 17, 2012 8:28 PM more detail
    Wednesday, October 17, 2012 8:26 PM

Answers

  • A couple of things going on here.  First if you're using NuGet then the packages are stored per solution in the Packages directory.  When you start a build NuGet is going to verify the solution's Packages directory contains the correct version of each referenced assembly.  Within each project is a config file that specifies the NuGet packages that it relies on.  Each solution has to verify and download its own copy of the packages.  This complies with the "solution is the root of the world" philosophy that VS uses.

    Package Restore is an interesting beast in the sense that they "broke" it a version or two back, at least in my opinion.  Initially PR would pull down the packages when you first did a build.  The packages were not stored in CM so if you wiped your solution and did a fresh get from CM then the packages would have to be downloaded again.  In the last version of NuGet they changed it such that it adds the packages to CM automatically but will pull down the correct version if it can't find it.  This can cause problems if you're not careful.  Another big change that was made is that nuget.exe is actually a smaller bootstrapper now that calls out to the public NuGet site to download an updated version.  The theory being that you'd always want the latest NuGet version.  At the same time they move the PR setting from the solution file to a global VS setting which will cause problems if you use automated builds.

    The way we work around it is that we have the .nuget folder in the root of each of our solutions.  We checked the old version of nuget.exe and the .targets file into CM as well.  We do not update to the newer version.  Now the build never tries to pull down a newer version.  Furthermore when we add packages from NuGet it (generally) doesn't try to add them to CM.  We pull the packages on the first build, which works for what we want.  Furthermore each of our solutions has the old setting to enable PR.  We do use the latest NuGet Package Manager so the option exists in VS Tools\Options to enable PR but it doesn't impact our builds.

    To get back to your problem you should see the Packages directory in each of your solutions so there should be no conflicts unless you have multiple solutions open at the same time and/or all your solutions share the same root. In that case you can get into build problems because VS, post build, may still have files open. Historically you would also probably see frequent build errors about other output files not being updateable but that seemed more common with native code then managed.  To help narrow down the actual problem I'd recommend cleaning your solution (including Packages) and building a single solution.  Verify the Packages folder is correct and then build the next solution.  In theory this should work but if the solutions share the same root and/or projects are using different versions of the packages you could run into issues.

    Michael Taylor - 10/17/2012
    http://msmvps.com/blogs/p3net

    Wednesday, October 17, 2012 9:53 PM
    Moderator
  • My coworker came up with a short term fix.  Edit each proj file that is shared across solutions and add a new hintpath that is relative to the current solution (rather than the original solution where the nuget reference was established).  

    <Reference Include="Castle.Windsor"> <SpecificVersion>False</SpecificVersion> <!-- Original HintPath -->

    <HintPath>..\..\..\..\..\Services\Windows\BatchCleanup\packages\Castle.Windsor.3.1.0\lib\net40\Castle.Windsor.dll</HintPath>

    <!-- add me! --> <HintPath>$(SolutionDir)\packages\Castle.Windsor.3.1.0\lib\net40\Castle.Windsor.dll</HintPath> </Reference>

    Tuesday, October 23, 2012 3:49 PM

All replies

  • A couple of things going on here.  First if you're using NuGet then the packages are stored per solution in the Packages directory.  When you start a build NuGet is going to verify the solution's Packages directory contains the correct version of each referenced assembly.  Within each project is a config file that specifies the NuGet packages that it relies on.  Each solution has to verify and download its own copy of the packages.  This complies with the "solution is the root of the world" philosophy that VS uses.

    Package Restore is an interesting beast in the sense that they "broke" it a version or two back, at least in my opinion.  Initially PR would pull down the packages when you first did a build.  The packages were not stored in CM so if you wiped your solution and did a fresh get from CM then the packages would have to be downloaded again.  In the last version of NuGet they changed it such that it adds the packages to CM automatically but will pull down the correct version if it can't find it.  This can cause problems if you're not careful.  Another big change that was made is that nuget.exe is actually a smaller bootstrapper now that calls out to the public NuGet site to download an updated version.  The theory being that you'd always want the latest NuGet version.  At the same time they move the PR setting from the solution file to a global VS setting which will cause problems if you use automated builds.

    The way we work around it is that we have the .nuget folder in the root of each of our solutions.  We checked the old version of nuget.exe and the .targets file into CM as well.  We do not update to the newer version.  Now the build never tries to pull down a newer version.  Furthermore when we add packages from NuGet it (generally) doesn't try to add them to CM.  We pull the packages on the first build, which works for what we want.  Furthermore each of our solutions has the old setting to enable PR.  We do use the latest NuGet Package Manager so the option exists in VS Tools\Options to enable PR but it doesn't impact our builds.

    To get back to your problem you should see the Packages directory in each of your solutions so there should be no conflicts unless you have multiple solutions open at the same time and/or all your solutions share the same root. In that case you can get into build problems because VS, post build, may still have files open. Historically you would also probably see frequent build errors about other output files not being updateable but that seemed more common with native code then managed.  To help narrow down the actual problem I'd recommend cleaning your solution (including Packages) and building a single solution.  Verify the Packages folder is correct and then build the next solution.  In theory this should work but if the solutions share the same root and/or projects are using different versions of the packages you could run into issues.

    Michael Taylor - 10/17/2012
    http://msmvps.com/blogs/p3net

    Wednesday, October 17, 2012 9:53 PM
    Moderator
  • My coworker came up with a short term fix.  Edit each proj file that is shared across solutions and add a new hintpath that is relative to the current solution (rather than the original solution where the nuget reference was established).  

    <Reference Include="Castle.Windsor"> <SpecificVersion>False</SpecificVersion> <!-- Original HintPath -->

    <HintPath>..\..\..\..\..\Services\Windows\BatchCleanup\packages\Castle.Windsor.3.1.0\lib\net40\Castle.Windsor.dll</HintPath>

    <!-- add me! --> <HintPath>$(SolutionDir)\packages\Castle.Windsor.3.1.0\lib\net40\Castle.Windsor.dll</HintPath> </Reference>

    Tuesday, October 23, 2012 3:49 PM
  • Apparently, this is a source of pain for others as well and may possibly be addressed in a future NUGET.

    Nuget discussion

    Saturday, October 27, 2012 2:30 PM