diff --git a/eng/verify-binding-redirects.ps1 b/eng/verify-binding-redirects.ps1 index 446769835c..b18c079b8a 100644 --- a/eng/verify-binding-redirects.ps1 +++ b/eng/verify-binding-redirects.ps1 @@ -1,13 +1,9 @@ $ErrorActionPreference = "Stop" Set-StrictMode -Version Latest -$script:isCI = $env:TF_BUILD -eq 'true' -or $env:CI -eq 'true' - -# Verifies that binding redirects in source app.config files match the actual -# assembly versions of the DLLs shipped in the extracted nupkg packages. -# -# In CI: validates and fails with instructions to run locally. -# Locally: auto-fixes the source app.config files with the correct versions. +# Verifies that no binding redirects exist in source app.config files. +# Binding redirects are a legacy mechanism that causes version mismatches +# and should not be used. See https://github.com/microsoft/vstest/issues/15765. # Each source app.config maps to a specific exe that ships in the packages. $script:AppConfigs = @( @@ -16,36 +12,6 @@ $script:AppConfigs = @( @{ Config = "src/datacollector/app.config"; ExeName = "datacollector.exe" } ) -function Find-ExeInPackages { - param( - [string] $ExeName, - [string[]] $PackageDirs - ) - - foreach ($dir in $PackageDirs) { - $found = Get-ChildItem $dir -Recurse -Filter $ExeName -File -ErrorAction SilentlyContinue - if ($found) { - # Prefer the one closest to a net462 or root layout (not nested in TestHostNetFramework). - $preferred = $found | Where-Object { $_.FullName -notlike "*TestHostNetFramework*" } | Select-Object -First 1 - if ($preferred) { return $preferred.DirectoryName } - return $found[0].DirectoryName - } - } - - return $null -} - -function Get-ManagedAssemblyVersion { - param([string] $DllPath) - - try { - return [System.Reflection.AssemblyName]::GetAssemblyName($DllPath).Version.ToString() - } - catch { - return $null - } -} - function Verify-BindingRedirects { param( [Parameter(Mandatory)] @@ -58,7 +24,6 @@ function Verify-BindingRedirects { $repoRoot = Resolve-Path "$PSScriptRoot/.." $errors = @() - $configsToFix = @{} foreach ($entry in $script:AppConfigs) { $configPath = Join-Path $repoRoot $entry.Config @@ -67,31 +32,12 @@ function Verify-BindingRedirects { continue } - $deployDir = Find-ExeInPackages -ExeName $entry.ExeName -PackageDirs $PackageDirs - if (-not $deployDir) { - Write-Host "Skipping $($entry.ExeName): not found in any extracted package." - continue - } - - Write-Host "Checking assembly redirects for $($entry.ExeName) (from '$deployDir')..." + Write-Host "Checking $($entry.Config) has no binding redirects..." [xml]$xml = Get-Content $configPath -Raw $nsMgr = New-Object System.Xml.XmlNamespaceManager($xml.NameTable) $nsMgr.AddNamespace("asm", "urn:schemas-microsoft-com:asm.v1") - # Build search directories from probing paths in the config. - $searchDirs = @($deployDir) - $probingNodes = $xml.SelectNodes("//asm:probing", $nsMgr) - foreach ($probing in $probingNodes) { - $privatePath = $probing.GetAttribute("privatePath") - if ($privatePath) { - foreach ($subPath in $privatePath -split ";") { - $probingDir = Join-Path $deployDir $subPath.Trim() - if (Test-Path $probingDir) { $searchDirs += $probingDir } - } - } - } - $dependentAssemblies = $xml.SelectNodes("//asm:dependentAssembly", $nsMgr) foreach ($dep in $dependentAssemblies) { $identity = $dep.SelectSingleNode("asm:assemblyIdentity", $nsMgr) @@ -99,113 +45,22 @@ function Verify-BindingRedirects { if (-not $identity -or -not $redirect) { continue } $assemblyName = $identity.GetAttribute("name") - $currentNewVersion = $redirect.GetAttribute("newVersion") - $currentOldVersion = $redirect.GetAttribute("oldVersion") - - # Look for the assembly DLL in each search directory. - $dllPath = $null - foreach ($dir in $searchDirs) { - $candidate = Join-Path $dir "$assemblyName.dll" - if (Test-Path $candidate) { $dllPath = $candidate; break } - } - - if (-not $dllPath) { - Write-Host " $assemblyName - not found in package layout, skipping." - continue - } - - $actualVersion = Get-ManagedAssemblyVersion -DllPath $dllPath - if (-not $actualVersion) { - Write-Host " $assemblyName - could not read version (native or corrupt?), skipping." - continue - } - - if ($currentNewVersion -eq $actualVersion) { - Write-Host " $assemblyName - OK ($actualVersion)" - continue - } - - # newVersion needs updating, and the upper bound of oldVersion range too. - $newOldVersion = $currentOldVersion - if ($currentOldVersion -match '^(.*)-(.*)$') { - $newOldVersion = "$($Matches[1])-$actualVersion" - } - - $errors += "$($entry.ExeName): $assemblyName redirect newVersion is '$currentNewVersion' but actual assembly version is '$actualVersion'" - - if (-not $configsToFix.ContainsKey($configPath)) { - $configsToFix[$configPath] = @() - } - - $configsToFix[$configPath] += @{ - AssemblyName = $assemblyName - OldNewVersion = $currentNewVersion - NewNewVersion = $actualVersion - OldOldVersion = $currentOldVersion - NewOldVersion = $newOldVersion - } - - if ($script:isCI) { - Write-Host " $assemblyName - MISMATCH: expected $actualVersion, found $currentNewVersion" -ForegroundColor Red - } - else { - Write-Host " $assemblyName - FIXING: $currentNewVersion -> $actualVersion (oldVersion: $currentOldVersion -> $newOldVersion)" -ForegroundColor Yellow - } + $errors += "$($entry.Config): has binding redirect for '$assemblyName'. Remove it." + Write-Host " FAIL: found binding redirect for '$assemblyName'" -ForegroundColor Red } - } - - # Apply fixes using XML DOM with whitespace preservation. - if (-not $script:isCI) { - foreach ($configPath in $configsToFix.Keys) { - $xmlDoc = New-Object System.Xml.XmlDocument - $xmlDoc.PreserveWhitespace = $true - $xmlDoc.Load($configPath) - - $nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable) - $nsMgr.AddNamespace("asm", "urn:schemas-microsoft-com:asm.v1") - foreach ($fix in $configsToFix[$configPath]) { - $nodes = $xmlDoc.SelectNodes("//asm:dependentAssembly[asm:assemblyIdentity[@name='$($fix.AssemblyName)']]/asm:bindingRedirect", $nsMgr) - $applied = $false - foreach ($node in $nodes) { - if ($node.GetAttribute("newVersion") -eq $fix.OldNewVersion) { - $node.SetAttribute("oldVersion", $fix.NewOldVersion) - $node.SetAttribute("newVersion", $fix.NewNewVersion) - $applied = $true - } - } - - if (-not $applied) { - Write-Error "Failed to apply binding redirect fix for '$($fix.AssemblyName)' in '$configPath'. The expected redirect node was not found." - } - } - - # Preserve the original BOM if present. - $bom = [System.IO.File]::ReadAllBytes($configPath) - $hasBom = $bom.Length -ge 3 -and $bom[0] -eq 0xEF -and $bom[1] -eq 0xBB -and $bom[2] -eq 0xBF - $encoding = if ($hasBom) { New-Object System.Text.UTF8Encoding($true) } else { New-Object System.Text.UTF8Encoding($false) } - $writer = New-Object System.IO.StreamWriter($configPath, $false, $encoding) - $xmlDoc.Save($writer) - $writer.Dispose() - Write-Host "Updated '$configPath'." -ForegroundColor Green + if (-not $errors) { + Write-Host " OK - no binding redirects." } } if ($errors) { - if ($script:isCI) { - $message = "Assembly binding redirect mismatches detected:`n" - $message += ($errors -join "`n") - $message += "`n`nTo fix this, run the following command locally after building and packing:`n" - $message += " .\build.cmd -c $Configuration`n" - $message += "This will rebuild, pack, and auto-update the app.config files with the correct versions.`n" - $message += "Then commit the updated app.config files." - Write-Error $message - } - else { - Write-Host "`nFixed $($errors.Count) binding redirect(s). Please commit the updated app.config files." -ForegroundColor Green - } + $message = "Binding redirects are not allowed in app.config files:`n" + $message += ($errors -join "`n") + $message += "`n`nSee https://github.com/microsoft/vstest/issues/15765 for details." + Write-Error $message } else { - Write-Host "All binding redirects match their DLL versions." + Write-Host "No binding redirects found in any app.config - good." } } diff --git a/src/datacollector/app.config b/src/datacollector/app.config index 2744e280a0..246305763e 100644 --- a/src/datacollector/app.config +++ b/src/datacollector/app.config @@ -11,36 +11,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/testhost.x86/app.config b/src/testhost.x86/app.config index c6e47644e1..b1d17fc9c6 100644 --- a/src/testhost.x86/app.config +++ b/src/testhost.x86/app.config @@ -11,44 +11,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/vstest.console/app.config b/src/vstest.console/app.config index f2bfcfed8c..a1a7d110a7 100644 --- a/src/vstest.console/app.config +++ b/src/vstest.console/app.config @@ -11,47 +11,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -