NuGet auto package restore does not work with MSBuild

125,445

Solution 1

UPDATED with latest official NuGet documentation as of v3.3.0

Package Restore Approaches

NuGet offers three approaches to using package restore.


Automatic Package Restore is the NuGet team's recommended approach to Package Restore within Visual Studio, and it was introduced in NuGet 2.7. Beginning with NuGet 2.7, the NuGet Visual Studio extension integrates into Visual Studio's build events and restores missing packages when a build begins. This feature is enabled by default, but developers can opt out if desired.


Here's how it works:

  1. On project or solution build, Visual Studio raises an event that a build is beginning within the solution.
  2. NuGet responds to this event and checks for packages.config files included in the solution.
  3. For each packages.config file found, its packages are enumerated and Checked for exists in the solution's packages folder.
  4. Any missing packages are downloaded from the user's configured (and enabled) package sources, respecting the order of the package sources.
  5. As packages are downloaded, they are unzipped into the solution's packages folder.

If you have Nuget 2.7+ installed; it's important to pick one method for > managing Automatic Package Restore in Visual Studio.

Two methods are available:

  1. (Nuget 2.7+): Visual Studio -> Tools -> Package Manager -> Package Manager Settings -> Enable Automatic Package Restore
  2. (Nuget 2.6 and below) Right clicking on a solution and clicking "Enable Package Restore for this solution".


Command-Line Package Restore is required when building a solution from the command-line; it was introduced in early versions of NuGet, but was improved in NuGet 2.7.

nuget.exe restore contoso.sln

The MSBuild-integrated package restore approach is the original Package Restore implementation and though it continues to work in many scenarios, it does not cover the full set of scenarios addressed by the other two approaches.

Solution 2

If you are using Visual Studio 2017 or later which ships with MSBuild 15 or later, and your .csproj files are in the new PackageReference format, the simplest method is to use the new MSBuild Restore target.


No-one has actually answered the original question, which is "how do I get NuGet packages to auto-restore when building from the command-line with MSBuild?" The answer is: unless you are using the "Enable NuGet package restore" option (which is now deprecated as per this reference), you can't (but see below). If you are trying to do e.g. automated builds on a CI server, this sucks.

However there is a slightly roundabout way to get the desired behaviour:

  1. Download the latest NuGet executable from https://dist.nuget.org/win-x86-commandline/latest/nuget.exe and place it somewhere in your PATH. (You can do this as a pre-build step.)
  2. Run nuget restore which will auto-download all the missing packages.
  3. Run msbuild to build your solution.

Aside: while the new and recommended way to do auto package restore involves less clutter in your version control, it also makes command-line package restore impossible unless you jump through the extra hoop of downloading and running nuget.exe. Progress?

Solution 3

Nuget's Automatic Package Restore is a feature of the Visual Studio (starting in 2013), not MSBuild. You'll have to run nuget.exe restore if you want to restore packages from the command line.

You can also use the Enable Nuget Package Restore feature, but this is no longer recommended by the nuget folks because it makes intrusive changes to the project files and may cause problems if you build those projects in another solution.

Solution 4

It took me some time to figure out the whole picture and I'd like to share here.

Visual Studio has two approaches to use package restore: Automatic Package Restore and MSBuild-Integrated package restore. The 'MSBuild-Integrated Package Restore' restores packages DURING the building process that might cause issues in some scenarios. The 'Automatic Package Restore' is the recommended approach by the NuGet team.

There are several steps to to make 'Automatic Package Restore' work:

  1. In Visual Studio, Tools -> Extensions and Updates, Upgrade NuGet if there is a newer version (Version 2.7 or later)

  2. If you use TFS, in your solution's .nuget folder, remove the NuGet.exe and NuGet.targes files. Then edit NuGet.Config to not check in NuGet packages:

    <configuration>  
      <solution>  
        <add key="disableSourceControlIntegration" value="true" />  
      </solution>  
    </configuration> 
    

    If you checked in the solution's packages folder to TFS before, delete the folder and check in the deletion of package folder deletion.

    If you don't use TFS, delete the .nuget folder.

  3. In each project file (.csproj or .vbproj) in your solution, remove the line that references NuGet.targets file. The reference looks like this:

    <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
    

    Remove this line in every project file in your solution.

  4. In Visual Studio menu, either through

    Tools -> Options -> Package Manager -> General or Tools -> NuGet Package Manager -> Package Manager Settings

    please enable the following two options 1) 'Allow NuGet to download missing packages' 2) 'Automatically check for missing packages during build in Visual Studio'

  5. Test your package restore configuration by the following steps

    • Save your solution and close Visual Studio
    • Delete your solution's packages folder
    • Start Visual Studio, open your solution and rebuild it.

Solution 5

MSBuild 15 has a /t:restore option that does this. it comes with Visual Studio 2017.

If you want to use this, you also have to use the new PackageReference, which means replacing the packages.config file with elements like this (do this in *.csproj):

<ItemGroup>
  <!-- ... -->
  <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
  <!-- ... -->
</ItemGroup>

There is an automated migration to this format if you right click on 'References' (it might not show up if you just opened visual studio, rebuild or open up the 'Manage NuGet packages for solution' window and it will start appearing).

Share:
125,445
UserControl
Author by

UserControl

Updated on March 03, 2020

Comments

  • UserControl
    UserControl about 4 years

    I'm trying to build a solution with packages content missing (except repositories.config inside) with MSBuild 12.0. I expect it to auto restore all missing packages before building but this is not the case - MsBuild reports tons of errors:

    "are you missing a using directive or an assembly reference?"

    NuGet Manager is 2.7 (I see this in Visual Studio 2013 about box). I even tried to pass EnableNuGetPackageRestore=true parameter - no luck. What am I missing?

  • UserControl
    UserControl about 10 years
    There is no .nuget folder and never was. All packages.config files within project folders are in place.
  • Sumeshk
    Sumeshk about 10 years
    i think NuGet.exe and NuGet.targets will automatically restore all missing packages while building the app and you lost your NuGet.exe and NuGet.targets files , thats y it cause errors
  • UserControl
    UserControl about 10 years
    Thanks anyway -I appreciate any help!
  • Sayed Ibrahim Hashimi
    Sayed Ibrahim Hashimi about 10 years
    One of your steps is to remove <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />. Why would you do that?
  • Ying
    Ying about 10 years
    if you use 'MSBuild-Integrated Package Restore' approach (by right-clicking your solution's Enable NuGet Package Restore menu item), the Visual Studio will add those lines into all project in your solution.
  • Sayed Ibrahim Hashimi
    Sayed Ibrahim Hashimi about 10 years
    I think you're mistaken that is in the template itself. Without it your source files will not be built at all.
  • Ying
    Ying about 10 years
    The change in project file just removes the package download task during the middle of build -- it doesn't break the build because the above solution downloads all dependent packages before the build starts.
  • Owen Johnson
    Owen Johnson about 10 years
    I think he meant nuget.targets instead of Microsoft.CSharp.targets.
  • Owen Johnson
    Owen Johnson about 10 years
    docs.nuget.org/docs/workflows/… <- Here's the official docs of what Ying was trying to say.
  • Owen Johnson
    Owen Johnson about 10 years
    This is no longer recommended by nuget. See the docs. docs.nuget.org/docs/workflows/…
  • UserControl
    UserControl almost 10 years
    Ended up with similar solution (but placed nuget.exe to /trunk/ext). One step forward - two steps back :(
  • Teknikaali
    Teknikaali almost 10 years
    You need to run "nuget update -self" before using the restore-command if your NuGet version isn't at least 2.7. My NuGet was version 2.1 and didn't recognize the "restore" command before updating.
  • CZahrobsky
    CZahrobsky almost 10 years
    Ying is right... what everyone has ignored is the fact that Continuous Integration builds create their own temporary workspace AFTER the pre-build events, get sources, and then choke on NuGet references. This is THE FIX for TFS build automation.
  • Nelson Rothermel
    Nelson Rothermel over 9 years
    "causes problems if you build those projects in another solution" I haven't run into any problems yet and we have 3 solutions with dozens of projects each (many shared across solutions). Maybe I got lucky?
  • AnneTheAgile
    AnneTheAgile over 9 years
    @OwenJohnson, that doc isn't dated that I can see and I don't see how it says it is not recommended now? I'm on VS2013 and that button appears to work fine. I did not have the problem referenced, "So, you clicked "Enable Nuget Package Restore" and now your stuff doesn't build. The steps to fix it are painful, but less painful with this script. " github.com/owen2/AutomaticPackageRestoreMigrationScript Perhaps there is another doc that explains this further.
  • Owen Johnson
    Owen Johnson over 9 years
    Automatic package restore replaces the ms-build integrated restore. The document is the instructions on how to upgrade. If you aren't having problems with the msbuild-integrated method, you don't need to do anything. In the simplest cases, it works, but if you have CI servers, shared project references, or some other conditions, you might step on some nasty landmines and have incorrect hintpaths or other issues.
  • Woland
    Woland over 9 years
    This should be a correct anwer, not the one marked.
  • Owen Johnson
    Owen Johnson about 9 years
    @NelsonRothermel the most notable problematic situation that can happen is projects referencing nuget-delivered dlls to an foreign solution's packages folder, which might not be available when you build a solution.
  • Nelson Rothermel
    Nelson Rothermel about 9 years
    @OwenJohnson We have one common package folder for all solutions, so that's probably why we haven't run into issues.
  • TGarrett
    TGarrett almost 9 years
    This really does seem to be a little counter intuitive when it comes down to it, but you really do get more functionalities to add specific nuget packages back by using the command line. This solution worked for me while the auto restore failed.
  • Greg
    Greg over 8 years
    For VS 2015 and TFS, this will fix you up. The problem will be a reference not resolved, and often the issue is that the nuget package isn't being restored because the folder for the package already exists in the packages folder, but yet the package hasn't been fully expanded properly. (Such as missing a lib folder which should contain a .dll.) Delete the whole folder for the package within packages, and then right click at the solution level and choose to restore packages.
  • Steve Radich-BitShop.com
    Steve Radich-BitShop.com over 8 years
    I was using Jenkins and had to do this, it was a simple build step before calling msbuild - Windows batch file was the build step type and: cmd.exe /c "C:\Program Files\nuget\nuget.exe" restore <RelativePathToSln>.sln - I did the path to SLN as a habit / procedure just in case it didn't find sln file.
  • Guerry
    Guerry over 8 years
    This approach worked for me when setting up a restore on a Jenkins build. One important key for me was that the NuGet.Config had to be in the same directory as my .SLN file. No combination of other config file locations, including specifying -ConfigFile on the command line would work.
  • Cody
    Cody over 8 years
    I had to download the 3.0 + version for certain packages. dist.nuget.org/win-x86-commandline/v3.1.0-beta/nuget.exe
  • granadaCoder
    granadaCoder about 8 years
    Using this answer AND the doing the "remove old stuff" instructions"Performing the migration" at docs.nuget.org/consume/package-restore/… , I was able to find success.
  • MytyMyky
    MytyMyky about 8 years
    the .nuget folder is a Visual Studio generated folder, that appears only when you enable automatic package restore. It is useful to have the nuget.exe in your code repo, as you can reference it in your builds, as is the nuget.config (especially if you need to get packages from multiple repos).
  • Jahmic
    Jahmic almost 8 years
    If you are constantly building from a fresh set of code (CI), this is the way to go.
  • Alain
    Alain almost 8 years
    This isn't working for me. Even after a successful nuget restore, msbuild isn't finding the referenced assemblies. Created a new question here stackoverflow.com/questions/38100358/…
  • XDS
    XDS over 7 years
    I kinda like this approach because it guarantees that each solution/project relies on the version of nuget it was created with. In due time this can prove vital if you work in a company with old projects which were created using old versions of nuget. A dev can maintain such projects without having to worry about whether the system-wide nuget.exe will break things because each project has its own "local flavor" of nuget.exe. As a last tip it's worth noting that with nuget 3.x+ we can restore packages like so: nuget.exe restore packages.config -PackagesDirectory path\to\packages
  • selalerer
    selalerer about 7 years
    For me, only adding the Nuget.Config, the .nuget folder (with nuget.exe and Nuget.Config) and adding .nuget as a project in the solution (doesn't appear in VS, I had to manually edit it in, copied it from another sln file) worked.
  • Neville
    Neville about 7 years
    The problem I have with this approach is that you'll need to edit any subsequent project file to add the restore step. you can add a "InvokeProcess" activity in TFS2012 or a "NuGetRestore" activity in TFS2013 build template to have this step execute on the build server. for InvokeProcess, pass in the attribute "SourcesDirectory" in 2012. In TFS 2013, just fill in the values as required. there's lots of blogs on how to do this.
  • dbruning
    dbruning almost 7 years
    Note that the "latest NuGet" executable above isn't necessarily the "latest" - it gave me v2.8. The nuget homepage has a link to latest nuget.exe which is 4.1.0 as at 2017-06-01
  • Ian Kemp
    Ian Kemp almost 7 years
    @dbruning Thanks, updated the answer with that info.
  • Owen Johnson
    Owen Johnson over 6 years
    Looks like things have changed again with NuGet 4 and .net standard.
  • Matthieu
    Matthieu almost 5 years
    You have to consider that the restore option of msbuild has subtle differences from nuget restore - see github.com/NuGet/Home/issues/7651#issuecomment-500842049 for example.
  • code4j
    code4j about 4 years
    I think this is the only nice solution when working with msbuild and nuget build target
  • T.S.
    T.S. almost 4 years
    This is not an answer to this question
  • granadaCoder
    granadaCoder almost 4 years
    So I verified that when you change the settings in Visual Studio (most of the answers here)....the above is actually what gets changed. the other "key" is <add key="enabled" value="False" />.
  • Dimitris Thomas
    Dimitris Thomas about 3 years
    Best answer. I wanted to nuke the packages dir every time i am building my solution (through a bat file) and then restore it. So i downloaded the latest nuget.exe from nuget.org/downloads, put it in the root of my project and then i give the command "call "nuget.exe" restore solution.sln". Works like a charm, thanks a lot
  • Nick Turner
    Nick Turner almost 3 years
    this fails on the mac if you have UWP in the solution