ps/Modules/Cole.PowerShell.Developer/Public/Find-MissingReferences.ps1

180 lines
6.3 KiB
PowerShell
Raw Permalink Normal View History

2023-05-30 22:51:22 -07:00
function Find-MissingReferences {
<#
.SYNOPSIS
Used to fetch all the assembly references and find which ones are missing from the folder presented by Path
.DESCRIPTION
Will check for files that should be present in the folder but which are not. Will assume any file loaded from the GAC is acceptable to not be present in the folder.
.PARAMETER Path
The folder where we should look for the files, or the full path of the file to be checked
.PARAMETER EntryPoint
Specify a specific file to consider the entry point for determining what is missing.
.PARAMETER ThrowOnError
Use this in a build environment if required
.PARAMETER Noisy
Be noisy. Show me all the stuff with warnings and such.
.PARAMETER Recursing
Don't set this
#>
[CmdletBinding()]
[OutputType([string[]])]
param (
[Parameter(Mandatory = $true)]
[string]$Path,
[Parameter(Mandatory = $false)]
[string]$EntryPoint,
[switch]$ThrowOnError,
[switch]$Noisy,
[switch]$Recursing
)
$logLead = Get-LogLeadName
if ($null -eq $global:allReferencedAssemblies) {
# You weren't supposed to set this, so if this value doesn't exist, then we can't be here
# Set the value to false so we can check it later for writing data out
$Recursing = $false
$global:allReferencedAssemblies = @()
}
if ($null -eq $global:loadedReferencesAlready) {
$global:loadedReferencesAlready = @()
}
if ($null -eq $global:missingReferences) {
$global:missingReferences = @()
}
# early exit if we already encountered this before
if ($global:missingReferences -contains $EntryPoint) {
return
}
if ($global:loadedReferencesAlready -contains $EntryPoint) {
return
}
# Check to see if it is in the GAC
try {
$assembly = [System.Reflection.Assembly]::Load($reference)
if ($null -ne $assembly) {
if ($Noisy) {
Write-Host "$($assembly.GetName().Name) - GAC? $($assembly.GlobalAssemblyCache) - $($assembly.Location)"
}
}
$global:loadedReferencesAlready += $assembly.GetName().Name
} catch {
# Keep going
}
if (!(Test-Path -Path $Path)) {
throw "$logLead : The path provided is not a valid path or does not exist."
}
$Path = Resolve-Path $Path
$item = Get-Item -Path $Path
$files = @()
if ($item.PSIsContainer) {
if ([string]::IsNullOrWhiteSpace($EntryPoint)) {
if ($Recursing) {
return
}
# We were given a folder, nut no EntryPoint, so just check all the files in the folder
$files = (Get-ChildItem (Join-Path -Path $Path "*.dll") -File).Name
} else {
if (!$EntryPoint.EndsWith(".dll")) {
$entryPointFileName = "$EntryPoint.dll"
}
$filePath = Join-Path -Path $Path -ChildPath $entryPointFileName
if (!(Test-Path $filePath)) {
$global:missingReferences += $EntryPoint
if ($Noisy) {
Write-Warning "$logLead : The file [$entryPointFileName] specified was not found in [$Path]"
}
return
}
$files = (Get-ChildItem $filePath -File).Name
}
} else {
# We were given a file directly
$EntryPoint = $item.Name
$Path = $item.Directory.FullName
$files = @($EntryPoint)
}
foreach ($file in $files) {
$fullName = (Join-Path -Path $Path -ChildPath $file)
$assembly = [System.Reflection.Assembly]::LoadFile($fullName)
$referencedAssemblies = $assembly.GetReferencedAssemblies()
$global:loadedReferencesAlready += $assembly.Name
# [System.IO.Path]::GetFileNameWithoutExtension($fullName)
foreach ($reference in $referencedAssemblies) {
$referenceName = $reference.Name
if ([string]::IsNullOrWhiteSpace($referenceName)) {
continue
}
if ($global:loadedReferencesAlready -contains $referenceName) {
continue
}
if ($global:allReferencedAssemblies -notcontains $referenceName) {
# Write-Host "add ref $referenceName"
$global:allReferencedAssemblies += $referenceName
$discard = Find-MissingReferences -Path $Path -EntryPoint $referenceName -Recursing -Noisy:$Noisy
}
}
$global:loadedReferencesAlready += $assembly.GetName().Name
}
if (!$Recursing) {
# cleanup the "missing" list because of GAC stuff
$missing = @()
foreach ($ref in $global:missingReferences) {
if ($global:loadedReferencesAlready -notcontains $ref) {
$missing += $ref
}
}
if ($Noisy) {
Write-Host "Found these referenced assemblies"
if ($null -ne ${function:Show-ListAsTable}) {
Show-ListAsTable ($global:allReferencedAssemblies | Sort-Object | Get-Unique)
} else {
Write-Host (($global:missingReferences | Sort-Object | Get-Unique) -Join "`n")
}
Write-Host "Found these available assemblies"
if ($null -ne ${function:Show-ListAsTable}) {
Show-ListAsTable ($global:loadedReferencesAlready | Sort-Object | Get-Unique)
} else {
Write-Host (($global:missingReferences | Sort-Object | Get-Unique) -Join "`n")
}
}
if (!(Test-IsCollectionNullOrEmpty $global:missingReferences)) {
Write-Host "Found these missing references"
if ($null -ne ${function:Show-ListAsTable}) {
Show-ListAsTable ($missing | Sort-Object | Get-Unique)
} else {
Write-Host (($missing | Sort-Object | Get-Unique) -Join "`n")
}
}
Remove-Variable -Name missingReferences -Scope Global
Remove-Variable -Name allReferencedAssemblies -Scope Global
Remove-Variable -Name loadedReferencesAlready -Scope Global
if ($ThrowOnError) {
if (!(Test-IsCollectionNullOrEmpty $missing)) {
throw "$logLead : You're missing some required references"
}
}
return $missing
}
}