IT:AD:NuGet:HowTo:Update Packages in the Solution/Is there a Better Way?
Summary
As they say in the advertisement, having Nuget manage your Packages and keep them up to date is practically seamless and automatic.
In reality…it's not.
Process
The official ways of updating packages (via Console or UI) are demonstrated here:
But the scripts leave us all …angry… in large solutions.
- awfully slow (there appears to be no caching for one).
- run into file locking issues (tfs file locks? file system file locks) where they abort in mid operation, in doing so, sometimes deleting the packages.config file.
I looked into whether there were better (ie faster ways).
Automating the default commands
A script I found out there that was the basis of the current script we use.
It's primitive, in that it just loops, with no caching.
# Script to upgrade all NuGet packages in solution to last version
function UpdateAll {
param($PackageID)
$packageManager = $host.PrivateData.packageManagerFactory.CreatePackageManager()
foreach ($project in Get-Project -all) {
$fileSystem = New-Object NuGet.PhysicalFileSystem($project.Properties.Item("FullPath").Value)
$repo = New-Object NuGet.PackageReferenceRepository($fileSystem, $packageManager.LocalRepository)
# for each package in the Packages folder,
# use update-package to invoke nuget.org and download the latest if any
# from there, use the default solution.
# ie...it's slow.
foreach ($package in $repo.GetPackages() | ? {$_.Id -eq $PackageID}) {
Update-Package $package.Id -Project:$project.Name
}
}
}
What's going on under the hood
But making it faster…is not easy…
According to: http://blog.davidebbo.com/2011/05/thoughts-on-installing-and-updating.html what happens is more than just a copy/update of the project files.
- Add references to assemblies contained in the package
- Add references to framework assemblies in the GAC
- Add content files to an app (e.g. JavaScript files, code files, …)
- Add assembly binding redirects to deal with version incompatibilities
- Perform config transformations, typically to add settings related to the package
- Bring in tools that can then be run from Package Manager Console
- Run PowerShell scripts which can do arbitrary things by automating the DTE object model
It explains why the Package Manager Console has a $dte reference -- it would be very hard to do the above from outside Visual Studio.
> It doesn't explain the File Locks which I see in a TFS scenario.
### Possible Alternate Scripts
The initial script I wrote * downloads the latest version installing in the packages folder * and caches it so it doesn't have to query it for the remaining packages. * manually updates the underlying packages.config in each project. * Then you have to close the solution and restart it so that it notices the packages are out of date, and redownloads it. * It works…sometimes. The last step sometimes fails.
- Which is therefore not good enough for production.