At work we had the following issue, we had a Silverlight project consuming some NuGet package, this project was being exposed in a Web application.
In order to keep our solution clean – we didn’t want an ‘assemblies’ folder – we used NuGet package restore.
We did it like the book said, don’t check in the packages folder, enable NuGet package restore, add the required repositories to the nuget.targets, you know the drill.
When building locally we didn’t have any issues. Everybody was able to run the project perfectly. The packages were downloaded from the repository when unavailable locally.
The issue rose when we committed our code to our source control system and ran builds of it with MSBuild.
In order to explain my issue I managed to create a very simple test case.
I created a solution with 2 projects, a web project, and a Silverlight project.
The NuGetTest.Client had a NuGet reference to the package ‘MvvmLight’.
When you commit code to source control and run builds of it with MSBuild, it is supposed to download the NuGet package, and then build of that.
However, if we invoke the build we are presented with the following error:
What? Why?
So I went to check the packages folder on the Build location:
It’s there! How could it not find the dll?
Time to dig deeper.
The command line executed for the project was simple:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /nologo /noconsolelogger "C:\Builds\1\NuGetTest\New Build Definition 1\Sources\Dev\NuGetTest.sln" /m:1 /fl /flp:"logfile=C:\Builds\1\NuGetTest\New Build Definition 1\Sources\Dev\NuGetTest.log;encoding=Unicode;verbosity=diagnostic" /p:SkipInvalidConfigurations=true /p:OutDir="C:\Builds\1\NuGetTest\New Build Definition 1\Binaries\\" /p:VCBuildOverride="C:\Builds\1\NuGetTest\New Build Definition 1\Sources\Dev\NuGetTest.sln.vsprops" /dl:WorkflowCentralLogger,"C:\Program Files\Microsoft Team Foundation Server 2010\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll";"Verbosity=Diagnostic;BuildUri=vstfs:///Build/Build/8;InformationNodeId=622;TargetsNotLogged=GetNativeManifest,GetCopyToOutputDirectoryItems,GetTargetPath;TFSUrl=http://localhost:8080/tfs/DefaultCollection;"*WorkflowForwardingLogger,"C:\Program Files\Microsoft Team Foundation Server 2010\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll";"Verbosity=Diagnostic;"
I slimmed it down to the real deal (removed logging), and ended up with this:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe "C:\Builds\1\NuGetTest\New Build Definition 1\Sources\Dev\NuGetTest.sln" /m:1 /p:SkipInvalidConfigurations=true
Now I download the latest version of the project locally, and execute that command line:
And we’re greeted with a lot of text, and at the end the same error. So it’s not the user that executes the build (he has sufficient rights).
What seems to happen here?
If we check the log we can see that the NuGetTest.Client is built because NuGetTest.Host depends on it:
Project "d:\Personal\Documents\Visual Studio 2010\Projects\NuGetTest\NuGetTest.Host\NuGetTest.Host.csproj" (2) is building "d:\Personal\Documents\Visual Studio 2010\Projects\NuGetTest\NuGetTest.Client\NuGetTest.Client.csproj" (3) on node 1 (GetXapOutputFile target(s)).
If we then continue reading the log file we can see that NuGet’s RestorePackages task is only executed after this task, which results in MSBuild trying to build the Silverlight project before all the required assemblies are downloaded.
How can we solve this? We can specify that the Silverlight project should be built before the web project, and thus forcing the RestorePackages to execute in order (before the build of the Silverlight project).
We can do this by going to project dependencies in the Solution Explorer, just do a right mouse on your solution and go to “Properties”.
In that window go to “Project Dependencies”:
In the “Project” dropdown you select your host project (here “NuGetTest.Host”), and check the checkbox of every Silverlight Project it depends on. This will make MSBuild explicitly build that project before continuing to the web project.
Good luck & have a good one!