nuget.exe, Visual Studio and packages.config

This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its dotnet CLI) and NuGet 7.9, as published in the MSBuild, .NET and NuGet documentation on learn.microsoft.com, which is the reference these pages are written and verified against. Material about .NET 11 / NuGet 8.0 is still in preview and is always flagged as such — never presented as baseline.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The C# Reference bibliography lists the reference material consulted while preparing these pages.

The dotnet CLI is one of four NuGet clients. nuget.exe is the standalone CLI, needed for packages.config projects and a few operations the SDK does not offer; Visual Studio has a graphical package manager and a PowerShell Package Manager Console; and packages.config is the older way to list a project’s packages. This page covers them for completeness and for migrations. The examples are not run here — this documentation was produced on Linux without Visual Studio — and come from the cited pages. A real packages.config project is walked through in ASP.NET MVC — NuGet packages and how their versions interlock.

nuget.exe

nuget.exe is a single file, not an installer: download https://dist.nuget.org/win-x86-commandline/latest/nuget.exe and put its folder on PATH. Version 5.0 and later need .NET Framework 4.7.2. nuget update -self updates it in place. The release feed (https://dist.nuget.org/tools.json) listed 7.9.0 as "ReleasedAndBlessed" on 2026-08-11 — the same NuGet version as SDK 10.0.4xx.

nuget restore Legacy.sln
nuget install Newtonsoft.Json -Version 13.0.3 -OutputDirectory packages
nuget update -self
  • All commands run on Windows. On macOS and Linux, nuget.exe needs Mono 4.4.2+ (a legacy path; Visual Studio for Mac is retired), and pack, restore and update have restrictions there.

  • The SDK covers most needs: pack, restore, delete, locals and push are available through dotnet. What nuget.exe adds is mainly packages.config restore and install, init/add for hierarchical folder feeds, spec and setapikey.

  • nuget install only extracts a package into a folder; it does not change any project — the one client operation that is not "record a reference, then restore".

Environment variables such as NUGET_PACKAGES, NUGET_HTTP_CACHE_PATH and NUGET_PLUGIN_PATHS apply to nuget.exe as to the SDK.

The Visual Studio package manager

Manage NuGet Packages (per project) and Manage NuGet Packages for Solution show four tabs:

  • Browse — search the selected source, see versions, dependencies, licence, vulnerabilities and deprecation.

  • Installed — the packages the project or solution references.

  • Updates — installed packages with newer versions, with multi-select update.

  • Consolidate (solution level only) — packages referenced at different versions by different projects, to align them on one. Central Package Management makes this tab unnecessary (Central Package Management).

The source drop-down lists the sources of the effective nuget.config; Tools > Options > NuGet Package Manager sets the default package format (PackageReference or packages.config) and the restore options.

The Package Manager Console

The console (Tools > NuGet Package Manager > Package Manager Console) is PowerShell inside Visual Studio on Windows, with cmdlets that act on the projects of the open solution:

Install-Package Humanizer.Core -Version 2.14.1 -ProjectName Ledgerline
Update-Package Humanizer.Core -ProjectName Ledgerline
Update-Package -Reinstall -ProjectName Legacy
Get-Package -Updates

Update-Package -Reinstall re-runs the installation of every package — the documented fix after retargeting a packages.config project to another framework. Outside Visual Studio the cmdlets do not exist; scripts use the dotnet CLI.

packages.config

Classic .NET Framework projects list packages in a packages.config file next to the project:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="jQuery" version="3.1.1" targetFramework="net46" />
  <package id="NLog" version="4.3.10" targetFramework="net46" />
</packages>

Each entry is an exact version (no ranges), the targetFramework it was installed for, and optionally allowedVersions (a range that limits updates) and developmentDependency. The format’s limits compared with PackageReference:

  • Every transitive package is listed — the file is the flattened graph, and updates rewrite many lines.

  • Packages are copied into a solution-level packages/ folder, and project files contain HintPath references into it.

  • No central versions, no lock files, no floating versions, no conditions per framework.

  • Install scripts and content files are applied once, at install time, by Visual Studio.

Migrating to PackageReference

Visual Studio’s migrator (right-click packages.config or References > Migrate packages.config to PackageReference…) rewrites the project to PackageReference items, keeping only top-level packages, and offers to back up the old files. Its limits:

  • Visual Studio only, and not for C++ or ASP.NET (web site and web application) projects.

  • install.ps1 and uninstall.ps1 scripts no longer run, content folder assets are not added (PackageReference uses contentFiles), and XDT transforms of web.config/app.config are not applied — the migrator lists packages affected by each.

  • allowedVersions constraints have no PackageReference equivalent.

Rolling back means restoring the backup the migrator created. A project migrated this way is still a classic (non-SDK) project; converting it to an SDK-style project is a separate step (SDK-Style Project Files).

Common mistakes

  • Using nuget.exe where dotnet suffices — one more tool to install and keep current.

  • Running Mono nuget.exe on Linux CI — use the SDK.

  • Migrating without checking the migrator’s compatibility list — install scripts and content silently stop applying.

  • Committing the packages/ folder — restore it instead.