74 lines
3.6 KiB
PowerShell
74 lines
3.6 KiB
PowerShell
param(
|
|
[Parameter(Mandatory)][string]$FirstPath,
|
|
[Parameter(Mandatory)][string]$SecondPath,
|
|
[Parameter(Mandatory)][string]$OutputPath,
|
|
[string]$CecilPath = (Join-Path $env:APPDATA 'XIVLauncher\addon\Hooks\dev\Mono.Cecil.dll')
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
Add-Type -Path $CecilPath
|
|
function Get-IcTypes($Types) {
|
|
foreach ($icType in $Types) {
|
|
$icType
|
|
Get-IcTypes $icType.NestedTypes
|
|
}
|
|
}
|
|
function Get-IcMetadata([string]$Path) {
|
|
$icFile = Get-Item -LiteralPath $Path
|
|
$icAsm = [Mono.Cecil.AssemblyDefinition]::ReadAssembly($icFile.FullName)
|
|
try {
|
|
$icAllTypes = @(Get-IcTypes $icAsm.MainModule.Types)
|
|
$icNamedTypes = @($icAllTypes | Where-Object { $_.FullName -match '^[\x20-\x7E]+$' })
|
|
$icShapes = [ordered]@{}
|
|
foreach ($icType in $icNamedTypes) {
|
|
$icShapes[$icType.FullName] = @(
|
|
"TYPE $($icType.Attributes) SIZE $($icType.ClassSize) PACK $($icType.PackingSize) BASE $($icType.BaseType.FullName)"
|
|
$icType.Interfaces | ForEach-Object { "INTERFACE $($_.InterfaceType.FullName)" }
|
|
$icType.Fields | ForEach-Object { "FIELD $($_.FullName) OFFSET $($_.Offset) FLAGS $($_.Attributes)" }
|
|
$icType.Methods | ForEach-Object { "METHOD $($_.FullName) FLAGS $($_.Attributes) IMPL $($_.ImplAttributes)" }
|
|
) | Sort-Object
|
|
}
|
|
[ordered]@{
|
|
File=$icFile.Name
|
|
Size=$icFile.Length
|
|
SHA256=(Get-FileHash -LiteralPath $icFile.FullName).Hash
|
|
Assembly=$icAsm.Name.FullName
|
|
MVID=$icAsm.MainModule.Mvid.ToString()
|
|
Architecture=$icAsm.MainModule.Architecture.ToString()
|
|
Attributes=@($icAsm.CustomAttributes | Where-Object {
|
|
$_.AttributeType.Name -match '^TargetFrameworkAttribute$|^Assembly(File|Informational)VersionAttribute$'
|
|
} | ForEach-Object {
|
|
[ordered]@{Type=$_.AttributeType.FullName; Values=@($_.ConstructorArguments | ForEach-Object { [string]$_.Value })}
|
|
})
|
|
References=@($icAsm.MainModule.AssemblyReferences | ForEach-Object { "$($_.Name) $($_.Version)" })
|
|
Resources=@($icAsm.MainModule.Resources | ForEach-Object { "$($_.ResourceType) $($_.Name)" })
|
|
TopLevelTypeCount=$icAsm.MainModule.Types.Count
|
|
TotalTypeCount=$icAllTypes.Count
|
|
AsciiNamedTypeCount=$icNamedTypes.Count
|
|
TypeShapes=$icShapes
|
|
}
|
|
} finally { $icAsm.Dispose() }
|
|
}
|
|
$icFirst = Get-IcMetadata $FirstPath
|
|
$icSecond = Get-IcMetadata $SecondPath
|
|
$icOnlyFirst = @($icFirst.TypeShapes.Keys | Where-Object { !$icSecond.TypeShapes.Contains($_) })
|
|
$icOnlySecond = @($icSecond.TypeShapes.Keys | Where-Object { !$icFirst.TypeShapes.Contains($_) })
|
|
$icChanges = foreach ($icName in $icFirst.TypeShapes.Keys) {
|
|
if (!$icSecond.TypeShapes.Contains($icName)) { continue }
|
|
$icDiff = @(Compare-Object $icFirst.TypeShapes[$icName] $icSecond.TypeShapes[$icName])
|
|
if ($icDiff.Count -gt 0) {
|
|
[ordered]@{Type=$icName; Differences=@($icDiff | ForEach-Object {
|
|
[ordered]@{OnlyIn=if ($_.SideIndicator -eq '=>') {'Second'} else {'First'}; Declaration=$_.InputObject}
|
|
})}
|
|
}
|
|
}
|
|
$icOutput = [ordered]@{
|
|
First=$icFirst
|
|
Second=$icSecond
|
|
AsciiTypesOnlyInFirst=$icOnlyFirst
|
|
AsciiTypesOnlyInSecond=$icOnlySecond
|
|
CommonTypeMetadataChanges=@($icChanges)
|
|
Limitation='Static declarations only; equal metadata does not establish equal method bodies or behavior. No target assembly was executed.'
|
|
}
|
|
$icOutput | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $OutputPath -Encoding utf8
|
|
"Saved comparison: $OutputPath"
|