Skip to content

Commit 039b7ea

Browse files
nohwndCopilot
andauthored
[fix] Harden binding redirect validation to catch missing DLLs (#15778)
* Error on binding redirects pointing to missing DLLs Change verify-binding-redirects.ps1 to fail when a binding redirect references a DLL that isn't in the package layout. Previously this was silently skipped, which allowed #15765 — a redirect for DiagnosticSource 8.0.0.1 shipped in the config but the DLL was excluded from the package. The whole-package-missing case (VMR) is still a skip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove stale DiagnosticSource and Encodings.Web redirects from vstest.console The hardened validation script caught two more orphaned binding redirects in vstest.console/app.config — both DLLs are explicitly excluded from the CLI package nuspec. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix review feedback: fail locally on missing-DLL errors - Missing-DLL errors now Write-Error instead of reporting success - CI message distinguishes version mismatches (auto-fixable) from missing-DLL errors (manual removal needed) - Addresses Copilot review comments on lines 133 and 138 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix em-dash encoding in verify-binding-redirects.ps1 Replace Unicode em-dash (U+2014) with ASCII hyphen in comments and strings. The em-dash gets corrupted to multi-byte garbage on CI's PowerShell, causing a parse error that breaks the entire validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove FileSystemGlobbing from allow-list It ships in the package, so allowing it would mask a future packaging regression. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 61f0fe2 commit 039b7ea

2 files changed

Lines changed: 43 additions & 16 deletions

File tree

eng/verify-binding-redirects.ps1

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@ $ErrorActionPreference = "Stop"
22
Set-StrictMode -Version Latest
33

44
$script:isCI = $env:TF_BUILD -eq 'true' -or $env:CI -eq 'true'
5+
$script:hasUnfixableErrors = $false
56

67
# Verifies that binding redirects in source app.config files match the actual
78
# assembly versions of the DLLs shipped in the extracted nupkg packages.
89
#
910
# In CI: validates and fails with instructions to run locally.
1011
# Locally: auto-fixes the source app.config files with the correct versions.
1112

13+
# Assemblies that have binding redirects but are intentionally NOT shipped in the
14+
# CLI/SDK package. These are loaded from Visual Studio at runtime when testhost
15+
# runs inside VS. A redirect without a DLL is safe here because the DLL comes
16+
# from VS's probing path, not from the package layout.
17+
$script:AllowMissingDlls = @(
18+
"Microsoft.VisualStudio.TestWindow.Interfaces"
19+
"Microsoft.VisualStudio.QualityTools.UnitTestFramework"
20+
)
21+
1222
# Each source app.config maps to a specific exe that ships in the packages.
1323
$script:AppConfigs = @(
1424
@{ Config = "src/vstest.console/app.config"; ExeName = "vstest.console.exe" }
@@ -110,7 +120,23 @@ function Verify-BindingRedirects {
110120
}
111121

112122
if (-not $dllPath) {
113-
Write-Host " $assemblyName - not found in package layout, skipping."
123+
if ($assemblyName -in $script:AllowMissingDlls) {
124+
Write-Host " $assemblyName - SKIP (allowed missing - loaded from VS at runtime)"
125+
continue
126+
}
127+
128+
# The deploy directory exists (package was found) but the DLL is missing.
129+
# A binding redirect pointing to a DLL that doesn't ship causes runtime
130+
# failures (e.g. #15765). Fail so the redirect gets removed.
131+
# This cannot be auto-fixed - the redirect must be manually removed or the DLL shipped.
132+
$errors += "$($entry.ExeName): $assemblyName has a binding redirect but the DLL is not in the package layout"
133+
$script:hasUnfixableErrors = $true
134+
if ($script:isCI) {
135+
Write-Host " $assemblyName - ERROR: binding redirect exists but DLL not found in package - remove the redirect or ship the DLL" -ForegroundColor Red
136+
}
137+
else {
138+
Write-Host " $assemblyName - ERROR: binding redirect exists but DLL not found in package - remove the redirect from $($entry.Config)" -ForegroundColor Red
139+
}
114140
continue
115141
}
116142

@@ -193,16 +219,26 @@ function Verify-BindingRedirects {
193219

194220
if ($errors) {
195221
if ($script:isCI) {
196-
$message = "Assembly binding redirect mismatches detected:`n"
222+
$message = "Assembly binding redirect errors detected:`n"
197223
$message += ($errors -join "`n")
198-
$message += "`n`nTo fix this, run the following command locally after building and packing:`n"
199-
$message += " .\build.cmd -c $Configuration`n"
200-
$message += "This will rebuild, pack, and auto-update the app.config files with the correct versions.`n"
201-
$message += "Then commit the updated app.config files."
224+
if ($configsToFix.Count -gt 0) {
225+
$message += "`n`nFor version mismatches, run the following command locally after building and packing:`n"
226+
$message += " .\build.cmd -c $Configuration`n"
227+
$message += "This will rebuild, pack, and auto-update the app.config files with the correct versions.`n"
228+
$message += "Then commit the updated app.config files."
229+
}
230+
if ($script:hasUnfixableErrors) {
231+
$message += "`n`nFor missing-DLL errors, remove the binding redirect from the app.config or add the DLL to the package."
232+
}
202233
Write-Error $message
203234
}
204235
else {
205-
Write-Host "`nFixed $($errors.Count) binding redirect(s). Please commit the updated app.config files." -ForegroundColor Green
236+
if ($configsToFix.Count -gt 0) {
237+
Write-Host "`nFixed $($configsToFix.Count) version mismatch(es). Please commit the updated app.config files." -ForegroundColor Green
238+
}
239+
if ($script:hasUnfixableErrors) {
240+
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)."
241+
}
206242
}
207243
}
208244
else {

src/vstest.console/app.config

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@
4343
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
4444
</dependentAssembly>
4545

46-
<dependentAssembly>
47-
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
48-
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.0" />
49-
</dependentAssembly>
50-
51-
<dependentAssembly>
52-
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
53-
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
54-
</dependentAssembly>
5546
</assemblyBinding>
5647
</runtime>
5748
<appSettings>

0 commit comments

Comments
 (0)