How to restore all nuget packages for a solution using MSBuild
I was pairing on some code this afternoon and ran into a problem; while our .NET solution would “**worked on our machine“™ but would fail on the build server with a message about missing references.
It turns out that ReSharper, which is used heavily on our team, offers a quick-fix option on a recognized but not imported type to “reference ‘{missing assembly}’ and use ‘{fully qualified name of type}’” and team members would sometimes use this quick-fix to add references instead of nuget. When the given .dll was found in a packages folder, the reference added to the project would be into the given package folder. Before version 8.0, however, ReSharper would add the assembly reference but not update the project’s packages.config file.
This would often go unnoticed on a local machine as the bits already existed in the packages folder, but when a build server checks out the code fresh or you happen to do a full clean that includes removing the packages folder, you may run into a race condition where the project without the reference in packages.config gets built before any project with a reference in packages.config. In that case, MSBuild cannot find the referenced package and the compile fails.
This is what was happening on our build server.
My pairing partner suggested that we write a quick build script to download all the packages before building the solution, which was much simpler than my previous approach of scanning the projects to look for missing references.
As suggested, then, here is an msbuild script that loops through all the packages.config files in your solution folder and restores all missing packages.
Include this target as a pre-build step and the symptom will disappear.
A simpler approach
Of course, now that I’ve finished a bit of internet digging reveals why you should always research existing solutions before building your own.
It turns out that a set of improvements were released in NuGet 2.7 that simplify this further.
Now restoring all nuget packages for a solution from the command-line is a simple one-liner:
nuget.exe restore path\to\solution.sln
And wrapping that in MSBuild is only a few more lines.
That’s much cleaner than my original implementation, but I’ve included it here for reference as it demonstrates batching and how you might exercise more explicit control over which packages get restored by a given build step.
Just patch ReSharper (a.k.a. the JetBrains folks rock!)
Finally, because this was a well known issue with ReSharper since early 2012, not only did the folks at JetBrains release a plugin for version 6 and 7 of ReSharper in late 2012 that used nuget to add the reference, but apparently they also fixed this issue in version 8.