-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFind-Depends.ps1
95 lines (76 loc) · 3.16 KB
/
Find-Depends.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<#
.DESCRIPTION
Find dependencies of a .NET DLL/EXE file.
.Parameter ExeOrDLLFile
File path of a .NET DLL/EXE.
.EXAMPLE
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)][string] $ExeOrDLLFile,
[Parameter(Mandatory = $false)][int] $MaxLayer = -1,
[Parameter(Mandatory = $false)][string] $ExemptNamePattern = "^(mscorlib|System(\.\S+)?|Microsoft.CSharp)$",
[switch] $NotStopAtFirstError
)
$ExemptNameRegex = if ([string]::IsNullOrEmpty($ExemptNamePattern)) {
New-Object System.Text.RegularExpressions.Regex("^###$")
} else {
$flag = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase -bor [System.Text.RegularExpressions.RegexOptions]::Compiled
New-Object System.Text.RegularExpressions.Regex($ExemptNamePattern, $flag)
}
$CheckedAssemblySet = New-Object 'System.Collections.Generic.HashSet[String]'([StringComparer]::OrdinalIgnoreCase)
function Throw_Errors {
param (
[string[]] $UpperFiles,
[string] $message
)
Write-Host -ForegroundColor Red "The $($UpperFiles.Count) upper level files as below:"
Write-Host -ForegroundColor Yellow ([String]::Join([System.Environment]::NewLine, $UpperFiles))
if ($NotStopAtFirstError) {
Write-Error $message
} else {
throw $message
}
}
function Find-OneDependency {
param (
[string] $filePath,
[int] $layer = 1,
[string[]] $UpperFiles = @()
)
Write-Output "`nLayer[$layer] Will check dependencies of $filePath"
$assembly = [System.Reflection.Assembly]::Load([System.IO.File]::ReadAllBytes($filePath)) # LoadFrom($filePath) #
$folder = [IO.Path]::GetDirectoryName($filePath)
$searchPaths = $folder + ";" + $env:Path
$references = $assembly.GetReferencedAssemblies()
$UpperFiles += "$($assembly.GetName().Version.ToString()) $filePath"
$toCheckList = @()
foreach ($rd in $references) {
if (-not $CheckedAssemblySet.Add("$($rd.Version) $($rd.FullName)")) {
# Write-Output "Already checked $rd"
continue
}
if ($ExemptNameRegex.IsMatch($rd.Name)) {
Write-Output "Skip checking $rd"
continue
}
$pattern = "^" + $rd.Name + "\.(dll|exe)$"
$dependPath = msr -p $searchPaths -f $pattern -l -W -PAC 2>$null -H 1 -J
if ([string]::IsNullOrEmpty($dependPath)) {
Throw_Errors $UpperFiles "Cannot find dependency: $rd for $filePath"
}
$da = [System.Reflection.Assembly]::Load([System.IO.File]::ReadAllBytes($dependPath)) #LoadFrom($dependPath) #
if (-not $rd.Version.Equals($da.GetName().Version)) {
Throw_Errors $UpperFiles "Inconsistent dependency: require $rd but found $da at $dependPath for $filePath"
}
Write-Output "Found dependency: $rd at $dependPath"
$toCheckList += $dependPath
if ($($layer -lt $MaxLayer) -or $($MaxLayer -lt 0)) {
$layer += 1
foreach ($dp in $toCheckList) {
Find-OneDependency $dependPath $layer $UpperFiles
}
}
}
}
Find-OneDependency $ExeOrDLLFile