NuGet: refreshing NuGet packages in packages folder during development
I'm working on NuGet packages in a Visual Studio project. On build I publish a new version of my nuget package to a repository (a directory on my system).
I don't increment version numbers after each change, i only want to do that on published versions of my packages.
To test out changes to the package in my solution where I already reference the package I want to pull in a new version of the package that has the same version number.
install-package does not have a -force option to force uninstall/install of the package with an unchanged version number.
The script below solves this issue. Save as Update-NuGetPackages.ps1 and put next to NuGet.exe.
Test out first on a copy of your Packages folder (copy to PackagesTest), so you have all parameters right. The script deletes all existing packages.
UPDATE: Updated the code so if package is deleted and install fails, an empty folder with the package name is created so after fixing the error the script can be called again to retry the update.
- <#
- .SYNOPSIS
- Update NuGet packages with same version of package.
- .DESCRIPTION
- During the development cycle version numbers of packages are often not changed,
- but the contents of the package itself is updates. Update-NuGetPackages.ps1
- refreshes all packages in a given packages directory.
- By default don't specify any sources, so NuGet.exe (version 1.3 and later) will use
- the NuGet.config which is stored in the AppData folder and shared between Visual Studio
- and NuGet.exe
- .PARAMETER PackagesPath
- Path to folder containing the packages to refresh.
- .PARAMETER PackagesSource
- Source where packages should be installed from. Post version 1.3 of NuGet.exe
- supports specifying multiple sources separated by ';'.
- Source paths may not contain PSDrives in its path, like product:\mypath.
- .PARAMETER IncludeDefaultSource
- Switch parameter to specify that the default NuGet packages source
- https://go.microsoft.com/fwlink/?LinkID=206669 should be included as a
- packages source. Don't specify this switch and dont use the PackagesSource
- parameter to let NuGet.exe use the sources specified in the NuGet.config.
- This functionality is available after release version 1.3 of NuGet.exe.
- If used together with the PackagesSource parameter a version newer than
- version 1.3 of NuGet.exe is required.
- .EXAMPLE
- PS C:\> Update-NuGetPackages.ps1 -PackagesSource c:\MyProduct\Packages
- Deleting package 'EntityFramework' version '4.1.10331.0'
- Deleting package 'MacawSolutionsFactory-Core' version '1.0.0'
- Deleting package 'MacawSolutionsFactory-Spf2010' version '1.0.0'
- Deleting package 'T4Scaffolding' version '1.0.0'
- Reinstalling package 'EntityFramework' version '4.1.10331.0'
- Successfully installed 'EntityFramework 4.1.10331.0'.
- Reinstalling package 'MacawSolutionsFactory-Core' version '1.0.0'
- 'T4Scaffolding (= 1.0.0)' not installed. Attempting to retrieve dependency from source...
- Done.
- Dependency 'EntityFramework (= 4.1.10311.0)' already installed.
- Successfully installed 'T4Scaffolding 1.0.0'.
- Successfully installed 'MacawSolutionsFactory-Core 1.0.0'.
- Reinstalling package 'MacawSolutionsFactory-Spf2010' version '1.0.0'
- Dependency 'T4Scaffolding (= 1.0.0)' already installed.
- Dependency 'EntityFramework (= 4.1.10311.0)' already installed.
- Successfully installed 'MacawSolutionsFactory-Spf2010 1.0.0'.
- Reinstalling package 'T4Scaffolding' version '1.0.0'
- Dependency 'EntityFramework (= 4.1.10311.0)' already installed.
- 'T4Scaffolding 1.0.0' already installed.
- Done.
- .EXAMPLE
- PS C:\> Update-NuGetPackages.ps1 -PackagesSource c:\MyProduct\Packages `
- -PackagesSource "c:\Dist\Feed1;c:\Dist\Feed2" -IncludeDefaultSource
- :
- .INPUTS
- System.String,System.String,System.Boolean
- .NOTES
- This script must be located next to NuGet.exe.
- This script requires a version later than the release version 1.3 of NuGet.exe
- when specifying multiple sources on the commandline and/or using the IncludeDefaultSource
- parameter.
- Version: 1.0
- Author: Serge van den Oever (http://weblogs.asp.net/soever)
- #>
- [CmdletBinding()]
- param
- (
- [Parameter(Position=0, Mandatory=$true)][String]$PackagesPath,
- [Parameter(Position=1, Mandatory=$false)][String]$PackagesSource = '',
- [Parameter(Position=2, Mandatory=$false)][Switch]$IncludeDefaultSource = $false
- )
- $nugetDefaultSource= 'https://go.microsoft.com/fwlink/?LinkID=206669'
- function Get-ScriptDirectory
- {
- $Invocation = (Get-Variable MyInvocation -Scope 1).Value
- Split-Path $Invocation.MyCommand.Path
- }
- $nugetExe = Join-Path -Path (Get-ScriptDirectory) -ChildPath 'nuget.exe'
- if (-not (Test-Path -Path $nugetExe)) { throw ("Expected NuGet.exe at path '{0}'" -f $nugetExe) }
- if (-not (Test-Path -Path $PackagesPath)) { throw ("Specified PackagesPath '{0}' does not exist" -f $PackagesPath) }
- $PackagesPath = Convert-Path -Path $PackagesPath
- # Collect packages
- $packageFolders = Get-ChildItem -Path $PackagesPath | Where-Object {$_.psIsContainer -eq $true}
- $packages = @()
- if ($packageFolders -ne $null) {
- $packageFolders | ForEach-Object {
- $packageFolder = Convert-Path -Path $_.FullName # Handle case where PSDrive is specified
- $packageFolderName = Split-Path -Path $packageFolder -Leaf
- $parts = $packageFolderName.split('.')
- $packageName = $parts[0]
- $packageVersion = $parts[1..$($parts.length-1)] -join '.'
- $packages += @{
- Name = $packageName;
- Version = $packageVersion;
- Folder = $packageFolder;
- }
- }
- }
- # Delete all package folders
- $packages | ForEach-Object {
- Write-Host ("Deleting package '{0}' version '{1}'" -f $_.Name, $_.Version)
- Remove-Item -Recurse -Force -Path $_.Folder -ErrorAction SilentlyContinue
- if (Test-Path -Path $_.Folder) { Write-Warning ("Can't remove folder '{0}'. Make sure it is not locked." -f $_.Folder) }
- }
- # Reinstall all packages
- $packages | ForEach-Object {
- Write-Host ("Reinstalling package '{0}' version '{1}'" -f $_.Name, $_.Version)
- if ($IncludeDefaultSource) {
- $source = $nugetDefaultSource
- } else {
- $source = ''
- }
- if ($PackagesSource -ne '') {
- if ($source -ne '') { $source += ';' }
- $source += (Convert-Path -Path $PackagesSource)
- }
- if ($source -ne '') {
- & $nugetExe install $_.Name -Version $_.Version -Source $source -OutputDirectory $PackagesPath
- } else {
- & $nugetExe install $_.Name -Version $_.Version -OutputDirectory $PackagesPath
- }
- if (-not (Test-Path -Path $_.Folder)) {
- New-Item -Path $_.Folder -Type Directory -Force
- Write-Warning ("Failed to reinstall package '{0}' version '{1}'. Created dummy directory '$($_.Folder). Fix error and try again." -f $_.Name, $_.Version)
- }
- }
- # Call Init.ps1 on all packages
- $packages | ForEach-Object {
- $initScript = Join-Path -Path $_.Folder -ChildPath 'Tools\Init.ps1'
- if (Test-Path -Path $initScript)
- {
- $rootPath = $_.Folder
- $toolsPath = Join-Path -Path $_.Folder -ChildPath 'Tools'
- $package = Get-Package -Filter $_.Name
- $project = $null
- & $initScript -rootPath $rootPath -toolsPath $toolsPath -package $package -project $project
- }
- }
- Write-Host 'Done.'