6

I'm working with a microservice architecture with core code that is shared via a nuget package. This all works pretty good except for the rare-ish occasions that I need to update one of my core nuget packages and then also update 10+ solutions to the latest one. With visual studio taking forever to load up I don't want to have to go in and open each one just to run the Update-Package command from the nuget Package Manager.

I looked into using the nuget.exe command line but the install option only downloads the package rather than install it into my project. I've tried searching for how to run the package manager outside visual studio, but the closest thing was this post two and a half years ago saying it's on the roadmap with an out-of-date link. I'm also unfamiliar with how asking for updates work on this site.

Does anyone know if there's some feature of nuget that I just missed? If not does anyone know of any alternative ways to update a nuget package for multiple solutions without having to wait through the horrendous Visual Studio load time every time?

Community
  • 1
  • 1
Paul Milla
  • 255
  • 1
  • 13
  • How about nuget cli? https://docs.nuget.org/ndocs/tools/nuget.exe-cli-reference too short for an answer :P – TigOldBitties Dec 02 '16 at 21:32
  • 2
    Doing a "nuget install My.Nuget.Package" only downloads it to my solution's packages/ folder. It doesn't actually update any usages to that package in the packages.json file nor update the hintpaths to it in the csproj file. While updating those 2 files manually might be faster than opening up visual studio it's a bit more error prone (and I'm known to make errors). – Paul Milla Dec 02 '16 at 21:40
  • 1
    Why is having a simple VS shortcut that edits files outside VS so rediculous? "nuget.exe install" and more specifically "nuget.exe update" get me most of the way there. Really the only thing left is for the "install" command to add an entry in packages.config/*.csproj file and for the "update" command to update the hintpath in the *.csproj file. I can make a quick script to run the command and do what I want, but I figured this must have been a solved problem by now and after not finding an immediate solution to it I thought I might ask for anyone else coming across this. – Paul Milla Dec 02 '16 at 22:12

1 Answers1

7

I ended up writing a quick powershell script to solve my problem. Here it is incase anyone else is interested:

param(
    [Parameter(Mandatory=$true)]$package,
    $solution = (Get-Item *.sln),
    $nuget = "nuget.exe"
)

& $nuget update "$solution" -Id "$package"

$sln = Get-Content $solution
[regex]$regex = 'Project\("{.*?}"\) = ".*?", "(.*?\.csproj)", "{.*?}"'
$csprojs = $sln | Select-String $regex -AllMatches | 
                  % {$_.Matches} |
                  % {$_.Groups[1].Value}

Foreach ($csproj_path in $csprojs) {
    $csproj_path = Get-Item $csproj_path
    Write-Host "Updating csproj: $csproj_path"

    [xml]$csproj = Get-Content $csproj_path
    Push-Location (Get-Item $csproj_path).Directory
    $reference = $csproj.Project.ItemGroup.Reference | ? {$_.Include -like "$package,*"}

    $old_include = [string]$reference.Include
    $old_hintpath = [string]$reference.HintPath
    $old_version = $old_include | Select-String 'Version=([\d\.]+?),' |
                                  % {$_.Matches} |
                                  % {$_.Groups[1].Value}

    $all_packages = Get-ChildItem $old_hintpath.Substring(0, $old_hintpath.IndexOf($package))
    $new_package_dir = $all_packages | ? {$_.Name -like "$package.[0-9.]*"} |
                                       ? {$_.Name -notlike "$package.$old_version"} |
                                       Select -First 1
    $new_version = $new_package_dir | Select-String "$package.([\d\.]+)" |
                                  % {$_.Matches} |
                                  % {$_.Groups[1].Value}

    $dll = Get-ChildItem -Path $new_package_dir.FullName -Recurse -Include *.dll | Select -First 1
    $reference.HintPath = [string](Get-Item $dll.FullName | Resolve-Path -Relative)
    $reference.Include = $reference.Include.Replace("Version=$old_version","Version=$new_version")

    Pop-Location
    $csproj.Save($csproj_path)
}
Paul Milla
  • 255
  • 1
  • 13
  • @Paul Milla Thanks for sharing your solution here. Please mark your answer which is benefit to other communities who has the same problem. – Weiwei Dec 05 '16 at 05:51
  • 1
    Warning! This does not address Assembly Binding Redirects. If you're project has conflicting transitive dependencies you will still need to refresh the binding redirects. https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/redirect-assembly-versions – bartonm Feb 22 '18 at 17:35