Describe the bug
We encountered this defect in a .NET custom action executing inside a WiX installer. The custom action loads a .NET Framework 4.8.1 assembly that constructs a ManagementClient, and the constructor throws a NotImplementedException.
When we investigated, we found the root cause: the WiX managed custom-action shim does not set AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName, leaving it null or empty. When TargetFrameworkName is missing, the .NET System.Uri class falls back to legacy behavior and decodes percent-encoded slashes and dots. ManagementClient's constructor calls DisableUriParserLegacyQuirks, which detects this via a URI round-trip test, then attempts a reflection-based workaround. In these environments, the workaround also fails, and the method throws.
The exception message confirms the root cause: TargetFramework= is followed by nothing, because TargetFrameworkName is empty:
System.NotImplementedException: Preserving slashes and dots escaped in System.Uri is not
supported in TargetFramework=. Expected=http://localhost/%2F., actual=http://localhost//.
During the investigation we also found that the same failure occurs when calling the ManagementClient constructor from a Windows PowerShell 5.1 session, which likewise does not configure TargetFrameworkName. We use PowerShell 5.1 as the reproduction vehicle in the steps below because it is far easier to set up than a WiX installer with a custom action.
Relevant source: ManagementClient.cs lines 49–72
To Reproduce
The crash happens inside the constructor — before any network call — so no live RabbitMQ server is required to reproduce it.
Prerequisites:
- Windows with Windows PowerShell 5.1 (
powershell.exe, not pwsh)
- A compiled copy of
EasyNetQ.Management.Client.dll (v3.0.1) and its dependencies (System.Text.Json.dll, etc.) in a single folder
Save the following script as Reproduce-ManagementClientBug.ps1 and run it from PowerShell 5.1:
#Requires -Version 5.1
param(
[Parameter(Mandatory)][string] $ManagementClientDllPath
)
$ErrorActionPreference = 'Stop'
try {
$libDir = Split-Path -Parent $ManagementClientDllPath
$resolverScript = {
param($sender, $resolveArgs)
$simpleName = $resolveArgs.Name.Split(',')[0].Trim()
$candidate = Join-Path $libDir "$simpleName.dll"
if (Test-Path $candidate) { return [System.Reflection.Assembly]::LoadFrom($candidate) }
return $null
}.GetNewClosure()
[System.AppDomain]::CurrentDomain.add_AssemblyResolve([System.ResolveEventHandler]$resolverScript)
[System.Reflection.Assembly]::LoadFrom($ManagementClientDllPath) | Out-Null
# Diagnose the environment
$tfn = ([System.AppDomain]::CurrentDomain.SetupInformation).TargetFrameworkName
Write-Host "TargetFrameworkName: $(if ([string]::IsNullOrEmpty($tfn)) { '(empty)' } else { $tfn })"
$testInput = 'http://localhost/' + [System.Uri]::EscapeDataString('/.')
$testOutput = (New-Object System.Uri $testInput).ToString()
Write-Host "URI round-trip ok: $($testInput -eq $testOutput)"
Write-Host " expected : $testInput"
Write-Host " actual : $testOutput"
Write-Host ""
# This line throws
$client = New-Object EasyNetQ.Management.Client.ManagementClient(
(New-Object System.Uri 'http://localhost:15672'),
'guest',
'guest'
)
Write-Host 'SUCCESS: ManagementClient created.'
}
catch {
$ex = $_.Exception
$depth = 0
while ($ex) {
Write-Host " [$depth] $($ex.GetType().FullName): $($ex.Message)"
$ex = $ex.InnerException
$depth++
}
exit 1
}
Run it from PowerShell 5.1:
powershell.exe -File .\Reproduce-ManagementClientBug.ps1 -ManagementClientDllPath "C:\path\to\EasyNetQ.Management.Client.dll"
Expected behavior
ManagementClient constructs successfully. If the URI quirks cannot be disabled via reflection, the constructor should either tolerate the condition gracefully (log a warning, no-op) or document that the reflection fix is best-effort and not throw.
Actual behavior
TargetFrameworkName: (empty)
URI round-trip ok: False
expected : http://localhost/%2F.
actual : http://localhost//
[0] System.NotImplementedException: Preserving slashes and dots escaped in System.Uri is
not supported in TargetFramework=. Expected=http://localhost/%2F., actual=http://localhost//.
Environment
|
|
EasyNetQ.Management.Client version |
3.0.1 |
| .NET Framework version of calling assembly |
4.8.1 |
| Host process |
Windows PowerShell 5.1 / WiX managed custom-action shim |
| OS |
Windows 11 Enterprise |
Additional context
The DisableUriParserLegacyQuirks method is trying to work around a known .NET Framework quirk where System.Uri decodes percent-encoded slashes and dots. That quirk is real, and the detection logic is correct. The problem is that when the reflection-based fix cannot be applied (because TargetFrameworkName is empty), the method throws instead of degrading gracefully.
Describe the bug
We encountered this defect in a .NET custom action executing inside a WiX installer. The custom action loads a
.NET Framework 4.8.1assembly that constructs aManagementClient, and the constructor throws aNotImplementedException.When we investigated, we found the root cause: the WiX managed custom-action shim does not set
AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName, leaving it null or empty. WhenTargetFrameworkNameis missing, the .NETSystem.Uriclass falls back to legacy behavior and decodes percent-encoded slashes and dots.ManagementClient's constructor callsDisableUriParserLegacyQuirks, which detects this via a URI round-trip test, then attempts a reflection-based workaround. In these environments, the workaround also fails, and the method throws.The exception message confirms the root cause:
TargetFramework=is followed by nothing, becauseTargetFrameworkNameis empty:During the investigation we also found that the same failure occurs when calling the
ManagementClientconstructor from a Windows PowerShell 5.1 session, which likewise does not configureTargetFrameworkName. We use PowerShell 5.1 as the reproduction vehicle in the steps below because it is far easier to set up than a WiX installer with a custom action.Relevant source:
ManagementClient.cslines 49–72To Reproduce
The crash happens inside the constructor — before any network call — so no live RabbitMQ server is required to reproduce it.
Prerequisites:
powershell.exe, notpwsh)EasyNetQ.Management.Client.dll(v3.0.1) and its dependencies (System.Text.Json.dll, etc.) in a single folderSave the following script as
Reproduce-ManagementClientBug.ps1and run it from PowerShell 5.1:Run it from PowerShell 5.1:
Expected behavior
ManagementClientconstructs successfully. If the URI quirks cannot be disabled via reflection, the constructor should either tolerate the condition gracefully (log a warning, no-op) or document that the reflection fix is best-effort and not throw.Actual behavior
Environment
EasyNetQ.Management.ClientversionAdditional context
The
DisableUriParserLegacyQuirksmethod is trying to work around a known .NET Framework quirk whereSystem.Uridecodes percent-encoded slashes and dots. That quirk is real, and the detection logic is correct. The problem is that when the reflection-based fix cannot be applied (becauseTargetFrameworkNameis empty), the method throws instead of degrading gracefully.