Skip to content

Instantly share code, notes, and snippets.

@chrisoldwood
Last active November 24, 2018 23:31
Show Gist options
  • Save chrisoldwood/23322ea073576fce7990 to your computer and use it in GitHub Desktop.
Save chrisoldwood/23322ea073576fce7990 to your computer and use it in GitHub Desktop.
Checks all packages.config files looking for version mismatches between different projects.
<#
.synopsis
Scans the packages.config files in a .Net solution looking for multiple
versions of the same package.
.description
Ideally your .Net based solutions should always be using a consistent
set of NuGet packages to avoid subtle bugs. This script, a companion to
CheckPackageCache, analyses all the NuGet packages used by your solution
and tells you if multiple package versions are being referenced.
The script terminates with a non-zero exit code if any duplicates are
found so it can be used as part of a build pipeline.
.parameter SolutionFolder
The path to the solution folder. Assumes the CWD by default.
.example
CheckPackageVersions c:\solution
#>
Param(
[Parameter(Position=0,Mandatory=0)]
[string] $SolutionFolder
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'stop'
$folder = '.'
if ($SolutionFolder -ne '')
{
$folder = $SolutionFolder
}
if (!(Test-Path $folder))
{
throw ("Invalid path: {0}" -f $folder)
}
$packages = @{}
$configFiles = @( Get-ChildItem -Path $folder -Recurse |
Where { $_.Name -eq 'packages.config' } )
foreach ($file in $configFiles)
{
$component = Split-Path -Leaf (Split-Path -Parent $file.FullName)
$lines = Get-Content $file.FullName
foreach ($line in $lines)
{
if ($line -match '^\s*<package id="(?<name>[^"]+)"\s*version="(?<version>[^"]+)"')
{
$packageName = $matches.name
$packageVersion = $matches.version
$package = New-Object psobject -Property @{
Name = $packageName
Version = $packageVersion
Component = $component
}
if (!$packages.ContainsKey($packageName))
{
$packages.Add($packageName, @{})
}
if (!$packages[$packageName].ContainsKey($packageVersion))
{
$packages[$packageName].Add($packageVersion, @())
}
$packages[$packageName][$packageVersion] += $package
}
}
}
$mismatches = @( $packages.GetEnumerator() |
Where { $_.Value.Count -gt 1 } |
Sort Name )
foreach ($mismatch in $mismatches)
{
$heading = 'Package: ' + $mismatch.Name
Write-Output $heading
Write-Output ('=' * $heading.Length)
foreach ($version in $mismatch.Value.GetEnumerator())
{
$versionNumber = $version.Name
$components = ($version.Value | ForEach { $_.Component }) -Join ', '
Write-Output ('{0}: {1}' -f $versionNumber,$components)
}
Write-Output ''
}
$mismatchCount = $mismatches.Count
if ($mismatchCount -ne 0)
{
Write-Warning "$mismatchCount package mismatch(es) found"
exit 1
}
else
{
Write-Output "No package mismatches found"
exit 0
}
@chrisoldwood
Copy link
Author

The script recursively looks for the packages.config files and compares the version numbers of each package to ensure that the same version of each package is referenced in each project.

When a mismatch is found it writes out which projects reference which version, e.g.

Package: Newtonsoft.Json
========================
6.0.1: Project-A, Project-B, Project-Z
6.0.9: Project-K

WARNING: 1 package mismatch(es) found

The script can be run automatically in a build pipeline as it correctly sets the exit code - 0 for success, or !0 if any mismatches have been found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment