diff --git a/eng/verify-binding-redirects.ps1 b/eng/verify-binding-redirects.ps1
index 446769835c..54f44dcc00 100644
--- a/eng/verify-binding-redirects.ps1
+++ b/eng/verify-binding-redirects.ps1
@@ -2,6 +2,7 @@ $ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
$script:isCI = $env:TF_BUILD -eq 'true' -or $env:CI -eq 'true'
+$script:hasUnfixableErrors = $false
# Verifies that binding redirects in source app.config files match the actual
# assembly versions of the DLLs shipped in the extracted nupkg packages.
@@ -9,6 +10,15 @@ $script:isCI = $env:TF_BUILD -eq 'true' -or $env:CI -eq 'true'
# In CI: validates and fails with instructions to run locally.
# Locally: auto-fixes the source app.config files with the correct versions.
+# Assemblies that have binding redirects but are intentionally NOT shipped in the
+# CLI/SDK package. These are loaded from Visual Studio at runtime when testhost
+# runs inside VS. A redirect without a DLL is safe here because the DLL comes
+# from VS's probing path, not from the package layout.
+$script:AllowMissingDlls = @(
+ "Microsoft.VisualStudio.TestWindow.Interfaces"
+ "Microsoft.VisualStudio.QualityTools.UnitTestFramework"
+)
+
# Each source app.config maps to a specific exe that ships in the packages.
$script:AppConfigs = @(
@{ Config = "src/vstest.console/app.config"; ExeName = "vstest.console.exe" }
@@ -110,7 +120,23 @@ function Verify-BindingRedirects {
}
if (-not $dllPath) {
- Write-Host " $assemblyName - not found in package layout, skipping."
+ if ($assemblyName -in $script:AllowMissingDlls) {
+ Write-Host " $assemblyName - SKIP (allowed missing - loaded from VS at runtime)"
+ continue
+ }
+
+ # The deploy directory exists (package was found) but the DLL is missing.
+ # A binding redirect pointing to a DLL that doesn't ship causes runtime
+ # failures (e.g. #15765). Fail so the redirect gets removed.
+ # This cannot be auto-fixed - the redirect must be manually removed or the DLL shipped.
+ $errors += "$($entry.ExeName): $assemblyName has a binding redirect but the DLL is not in the package layout"
+ $script:hasUnfixableErrors = $true
+ if ($script:isCI) {
+ Write-Host " $assemblyName - ERROR: binding redirect exists but DLL not found in package - remove the redirect or ship the DLL" -ForegroundColor Red
+ }
+ else {
+ Write-Host " $assemblyName - ERROR: binding redirect exists but DLL not found in package - remove the redirect from $($entry.Config)" -ForegroundColor Red
+ }
continue
}
@@ -193,16 +219,26 @@ function Verify-BindingRedirects {
if ($errors) {
if ($script:isCI) {
- $message = "Assembly binding redirect mismatches detected:`n"
+ $message = "Assembly binding redirect errors 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."
+ if ($configsToFix.Count -gt 0) {
+ $message += "`n`nFor version mismatches, 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."
+ }
+ if ($script:hasUnfixableErrors) {
+ $message += "`n`nFor missing-DLL errors, remove the binding redirect from the app.config or add the DLL to the package."
+ }
Write-Error $message
}
else {
- Write-Host "`nFixed $($errors.Count) binding redirect(s). Please commit the updated app.config files." -ForegroundColor Green
+ if ($configsToFix.Count -gt 0) {
+ Write-Host "`nFixed $($configsToFix.Count) version mismatch(es). Please commit the updated app.config files." -ForegroundColor Green
+ }
+ if ($script:hasUnfixableErrors) {
+ Write-Error "Missing-DLL binding redirect errors detected - these cannot be auto-fixed. Remove the redirect(s) listed above from the app.config file(s)."
+ }
}
}
else {
diff --git a/src/vstest.console/app.config b/src/vstest.console/app.config
index f2bfcfed8c..556125c5f6 100644
--- a/src/vstest.console/app.config
+++ b/src/vstest.console/app.config
@@ -43,15 +43,6 @@
-
-
-
-
-
-
-
-
-