Internet Sellout

Demand Unearned Rewards

Assembly Version

 

Copilot and I created this script. This script has 3 parameters, none is required.

  • -TargetDir is the path of a folder you want to examine. Or it will use the working dir.
  • -BindingRedirectsFile is a path to a file that you want to write redirects for all the assembly versions it finds in -TargetDir. It will replace all the contents so do not point it at a working .config file. If this is not present it will just print to the output.
  • -ExcludeNoPublicKeyToken just a flag to ignore assemblies with no public key token. Because those are probably your related project files.

Save this script to a file named assemblyversions.ps1, open a PowerShell command prompt to the dir so you can call

.\assemblyversions -TargetDir "C:\temp\bin" -BindingRedirectsFile "C:\temp\bindingsredirectfile.txt" -ExcludeNoPublicKeyToken

It is kinda slow because it calls PowerShell in a loop so that the locks on the file are released. It was the only way. The read-only version of loadfile didn't fully release.

Here is the script to save:
 

param(
    [string]$TargetDir = $PWD,
    [string]$BindingRedirectsFile = $null,
    [switch]$ExcludeNoPublicKeyToken
)

function Get-BindingRedirect {
    param($AssemblyName, $Version, $PublicKeyToken)
    @"
<dependentAssembly>
  <assemblyIdentity name="$AssemblyName" publicKeyToken="$PublicKeyToken" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-$Version" newVersion="$Version" />
</dependentAssembly>
"@
}

# Write the child script to a temp file
$childScriptPath = [System.IO.Path]::GetTempFileName() + ".ps1"
@'
param([string]$dll, [string]$dllName)
try {
    $a = [System.Reflection.Assembly]::LoadFile($dll)
    $n = $a.GetName()
    $v = $n.Version
    $pktBytes = $n.GetPublicKeyToken()
    if ($pktBytes -eq $null -or $pktBytes.Length -eq 0) { $pkt = 'null' } else { $pkt = ($pktBytes | ForEach-Object { $_.ToString('x2') }) -join '' }
    Write-Output ($n.Name + "|" + $v + "|" + $pkt)
} catch {
    Write-Output ("ERROR|" + $dllName + "|Could not load assembly")
}
'@ | Set-Content -Encoding UTF8 $childScriptPath

$results = @()
$redirects = @()

Get-ChildItem -Path $TargetDir -Filter *.dll | ForEach-Object {
    $dllPath = $_.FullName
    $dllName = $_.Name

    $output = powershell -NoProfile -File $childScriptPath -dll $dllPath -dllName $dllName
    $output = $output -replace "`r?`n", ""

    if ($output -like "ERROR|*") {
        $parts = $output -split "\|"
        $results += "${dllName}: Could not load assembly"
        return
    }

    $parts = $output -split "\|"
    if ($parts.Count -lt 3) {
        $results += "${dllName}: Could not parse assembly info"
        return
    }
    $asmName = $parts[0]
    $version = $parts[1]
    $pkt = $parts[2]

    $results += "${dllName}: $version (PublicKeyToken=$pkt)"

    if ($BindingRedirectsFile) {
        if ($ExcludeNoPublicKeyToken) {
            if ($pkt -ne "null") {
                $redirects += Get-BindingRedirect $asmName $version $pkt
            }
        } else {
            $redirects += Get-BindingRedirect $asmName $version $pkt
        }
    }
}

Remove-Item $childScriptPath -ErrorAction SilentlyContinue

$results | Write-Output

if ($BindingRedirectsFile) {
    $header = @"
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
"@
    $footer = @"
    </assemblyBinding>
  </runtime>
</configuration>
"@
    $content = $header + "`r`n" + ($redirects -join "`r`n") + "`r`n" + $footer
    Set-Content -Path $BindingRedirectsFile -Value $content
    Write-Output "Binding redirects written to $BindingRedirectsFile"
}

 

Comments are closed