Skip to content

Instantly share code, notes, and snippets.

@brianvanderlugt
Last active April 12, 2025 20:53
Show Gist options
  • Save brianvanderlugt/78cf683bb785422c529cd095c7be4f3b to your computer and use it in GitHub Desktop.
Save brianvanderlugt/78cf683bb785422c529cd095c7be4f3b to your computer and use it in GitHub Desktop.
PowerShell script to output graph dependency to help resolve nuget dependencies.
#Requires -RunAsAdministrator
# Pre-requisites
Install-Module PowerShellGet -Force # to install additional packages
Import-Module PowerShellGet -MinimumVersion 2.2.0
# Doesn't work because PowerShellGet doesn't support SemVer 2.0 yet. https://github.com/PowerShell/PowerShellGet/issues/222
Install-Package NuGet.Core,NuGet.ProjectModel
# Instead run. Recommmend copy as installs additional libraries already cover by NETStandard 2.0
nuget install -Framework NETStandard2.0 Nuget.ProjectModel # <- Copy required packages to C:\Program Files\PackageManagement\NuGet\Packages\
# Source: https://www.jerriepelser.com/blog/analyze-dotnet-project-dependencies-part-1/
param(
[ValidateScript({Test-Path -Path $(Resolve-Path -Path $_) -PathType Leaf})]
[String]$SolutionPath = '.\Path\TestFile.sln'
)
(Resolve-Path -Path C:\src\cleanspark\SitePlatform\CleanSpark.Site\CleanSpark.Site.sln).Path.Substring(0, 'C:\src\cleanspark\SitePlatform\CleanSpark.Site\CleanSpark.Site.sln'.LastIndexOf([System.IO.Path]::DirectorySeparatorChar))
$resolvedSolutionPath = (Resolve-Path -Path $SolutionPath).Path
Push-Location $resolvedSolutionPath.Substring(0, $resolvedSolutionPath.LastIndexOf([System.IO.Path]::DirectorySeparatorChar))
function Out-ReportDependency{
param(
[NuGet.ProjectModel.LockFileTargetLibrary] $projectLibrary,
[NuGet.ProjectModel.LockFileTarget] $lockFileTargetFramework,
[int] $indentLevel = 1
)
$indentation = $(New-Object System.String -ArgumentList ' ',($indentLevel * 2))
Write-Output "${indentation}$($projectLibrary.Name), v$($projectLibrary.Version)"
foreach ($childDependency in $projectLibrary.Dependencies){
$childLibrary = $lockFileTargetFramework.Libraries.Where({$_.Name -eq $childDependency.Id}) | select -First 1
Out-ReportDependency -projectLibrary $childLibrary -lockFileTargetFramework $lockFileTargetFramework -indentLevel ($indentLevel + 1)
}
}
try{
Get-ChildItem -Path 'C:\Program Files\PackageManagement\NuGet\Packages\' -Filter Nuget.* -Include *.dll -Recurse |
where{$_.FullName -like "*netstandard2.0*"} |
foreach{Add-Type -Path $_.FullName}
Add-Type -AssemblyName Newtonsoft.Json
dotnet msbuild $resolvedSolutionPath /t:GenerateRestoreGraphFile /p:RestoreGraphOutputPath=graph.dg
$fileText = Get-Content -Path .\graph.dg -Raw
$json = [Newtonsoft.Json.JsonConvert]::DeserializeObject($fileText, [Newtonsoft.Json.Linq.JObject])
$dependencyGraph = [NuGet.ProjectModel.DependencyGraphSpec]::new($json)
Write-Output "$(Get-Date): Direct dependencies`n`n"
foreach ($project in $dependencyGraph.Projects.Where({$_.RestoreMetadata.ProjectStyle -eq [NuGet.ProjectModel.ProjectStyle]::PackageReference})){
Write-Output $project.Name
foreach($targetFramework in $project.TargetFrameworks){
Write-Output " [{$targetFramework.FrameworkName}]"
foreach($dependency in $targetFramework.Dependencies){
Write-Output " $($dependency.Name), v$($dependency.LibraryRange.VersionRange.ToShortString())"
}
}
}
Write-Output "$(Get-Date): Transient dependencies`n`n"
foreach ($project in $dependencyGraph.Projects.Where({$_.RestoreMetadata.ProjectStyle -eq [NuGet.ProjectModel.ProjectStyle]::PackageReference})){
$runStatus = (dotnet restore "$($project.FilePath)")
$lockFilePath = Join-Path -Path $project.RestoreMetadata.OutputPath -ChildPath 'project.assets.json'
$lockFile = [NuGet.ProjectModel.LockFileUtilities]::GetLockFile($lockFilePath, [NuGet.Common.NullLogger]::Instance)
Write-Output $project.Name
foreach ($targetFramework in $project.TargetFrameworks){
Write-Output " [{$targetFramework.FrameworkName}]"
$lockFileTargetFramework = $null
$lockFileTargetFramework = $lockFile.Targets.Where({$_.TargetFramework -eq $targetFramework.FrameworkName}) | select -First 1
if ($null -ne $lockFileTargetFramework){
foreach($dependency in $targetFramework.Dependencies){
$projectLibrary = $lockFileTargetFramework.Libraries.Where({$_.Name -eq $dependency.Name}) | select -First 1
Out-ReportDependency -projectLibrary $projectLibrary -lockFileTargetFramework $lockFileTargetFramework
}
}
}
}
}
finally{
Pop-Location
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment