diff --git a/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs b/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs
index fba2e38..4f15082 100644
--- a/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs
+++ b/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs
@@ -158,6 +158,27 @@ public partial class MainWindowViewModel : ObservableObject
}
}
+ [RelayCommand]
+ private async Task CheckForInconsistentNugetPackageVersionsInSolutionFile(CancellationToken token)
+ {
+ SetBeginCommandState();
+ try
+ {
+ await Task.Run(
+ () =>
+ {
+ var results = PackageVersionConsistency.FindInconsistentNugetPackageVersions(SolutionFilePath);
+ SetCommandSuccessState($"{results.Count} packages with inconsistent versions", results);
+ },
+ token
+ );
+ }
+ catch (Exception e)
+ {
+ SetCommandFailureState("Failed to check for inconsistent package versions in solution file", e);
+ }
+ }
+
[RelayCommand]
private async Task CheckForMissingImplicitUsingsInSolutionFile(CancellationToken token)
{
diff --git a/DotNetSolutionTools.App/Views/MainWindow.axaml b/DotNetSolutionTools.App/Views/MainWindow.axaml
index a606c62..56bc704 100644
--- a/DotNetSolutionTools.App/Views/MainWindow.axaml
+++ b/DotNetSolutionTools.App/Views/MainWindow.axaml
@@ -31,7 +31,7 @@
-
+
+
diff --git a/DotNetSolutionTools.Core/PackageVersionConsistency.cs b/DotNetSolutionTools.Core/PackageVersionConsistency.cs
new file mode 100644
index 0000000..2025e8d
--- /dev/null
+++ b/DotNetSolutionTools.Core/PackageVersionConsistency.cs
@@ -0,0 +1,76 @@
+using DotNetSolutionTools.Core.Common;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Definition;
+using Microsoft.Build.Evaluation;
+using NuGet.Versioning;
+
+namespace DotNetSolutionTools.Core;
+
+public class PackageVersionConsistency
+{
+ public static List FindInconsistentNugetPackageVersions(string solutionFilePath)
+ {
+ var solutionFile = SolutionFile.Parse(solutionFilePath);
+ var csprojList = SlnHelper.GetCSharpProjectObjectsFromSolutionFile(solutionFile);
+ var packageList = new List<(string, NuGetVersion)>();
+ var outOfSyncPackages = new List<(string packageName, NuGetVersion version)>();
+ foreach (var project in csprojList)
+ {
+ var projectPackages = GetPackageVersions(project);
+ packageList.AddRange(projectPackages);
+ }
+
+ var groupedByPackage = packageList.GroupBy(s => s.Item1).ToList();
+ foreach (var package in groupedByPackage)
+ {
+ var versions = package.Select(s => s.Item2).Distinct().ToList();
+ if (versions.Count > 1)
+ {
+ outOfSyncPackages.Add((package.Key, versions.First()));
+ }
+ }
+
+ Console.WriteLine("Logging out of sync packages");
+ outOfSyncPackages.ForEach(s => Console.WriteLine(s.packageName));
+
+ return outOfSyncPackages.Select(s => s.packageName).ToList();
+ }
+
+ private static List<(string, NuGetVersion)> GetPackageVersions(ProjectRootElement project)
+ {
+ Project? evalProject = null;
+ try
+ {
+ evalProject = Project.FromProjectRootElement(
+ project,
+ new ProjectOptions { LoadSettings = ProjectLoadSettings.IgnoreMissingImports }
+ );
+ var packages = evalProject
+ .Items.Where(x => x.ItemType == "PackageReference" && x.HasMetadata("Version"))
+ .ToList();
+
+ var packageNameAndVersion = packages
+ .Select(x =>
+ (
+ x.EvaluatedInclude,
+ NuGetVersion.Parse(x.Metadata.First(s => s.Name == "Version").UnevaluatedValue)
+ )
+ )
+ .ToList();
+ return packageNameAndVersion;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ finally
+ {
+ if (evalProject is not null)
+ {
+ ProjectCollection.GlobalProjectCollection.UnloadProject(evalProject);
+ ProjectCollection.GlobalProjectCollection.TryUnloadProject(project);
+ }
+ }
+ }
+}