Search code examples
.net.net-assemblyassembly-binding-redirect

Assembly Binding Redirect does not work as Publisher Policy


I have the following assembly binding redirect:

<configuration> 
    <runtime> 
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
            <dependentAssembly> 
                <assemblyIdentity name="winfsp-msil" publicKeyToken="b099876d8fa9b1f3" culture="neutral" /> 
                <bindingRedirect oldVersion="1.0.0.0-1.1.17102.0" newVersion="1.1.17102.0" /> 
            </dependentAssembly> 
        </assemblyBinding> 
    </runtime> 
</configuration> 

When used as an app config this redirect works. It finds the assembly in the GAC and loads it correctly.

billziss@windows:~/Desktop/passthrough-dotnet-17101$ ./passthrough-dotnet.exe
usage: passthrough-dotnet OPTIONS
...

When used as a publisher policy it fails:

billziss@windows:~/Desktop/passthrough-dotnet-17101$ ./passthrough-dotnet.exe

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'winfsp-msil, Version=1.1.17101.0, Culture=neutral, PublicKeyToken=b099876d8fa9b1f3' or one of its dependencies. The system cannot find the file specified.
   at passthrough.Program.Main(String[] args)

The Assembly Binding Log Viewer reports:

*** Assembly Binder Log Entry  (4/13/2017 @ 10:50:50 AM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\Users\billziss\Desktop\passthrough-dotnet-17101\passthrough-dotnet.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = winfsp-msil, Version=1.1.17101.0, Culture=neutral, PublicKeyToken=b099876d8fa9b1f3
 (Fully-specified)
LOG: Appbase = file:///C:/Users/billziss/Desktop/passthrough-dotnet-17101/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = passthrough-dotnet.exe
Calling assembly : passthrough-dotnet, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: winfsp-msil, Version=1.1.17101.0, Culture=neutral, PublicKeyToken=b099876d8fa9b1f3
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Users/billziss/Desktop/passthrough-dotnet-17101/winfsp-msil.DLL.
LOG: Attempting download of new URL file:///C:/Users/billziss/Desktop/passthrough-dotnet-17101/winfsp-msil/winfsp-msil.DLL.
LOG: Attempting download of new URL file:///C:/Users/billziss/Desktop/passthrough-dotnet-17101/winfsp-msil.EXE.
LOG: Attempting download of new URL file:///C:/Users/billziss/Desktop/passthrough-dotnet-17101/winfsp-msil/winfsp-msil.EXE.
LOG: All probing URLs attempted and failed.

The policy.1.0.winfsp-msil appears to be in the GAC properly:

C:\Users\billziss\Desktop\passthrough-dotnet-17101>gacutil /l policy.1.0.winfsp-msil
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  policy.1.0.winfsp-msil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b099876d8fa9b1f3, processorArchitecture=MSIL

Number of items = 1

C:\Users\billziss\Desktop\passthrough-dotnet-17101>dir /s \windows\assembly\GAC_MSIL\policy.1.0.winfsp-msil
 Volume in drive C has no label.
 Volume Serial Number is CCB1-42FC

 Directory of C:\windows\assembly\GAC_MSIL\policy.1.0.winfsp-msil

04/12/2017  04:06 PM    <DIR>          .
04/12/2017  04:06 PM    <DIR>          ..
04/12/2017  04:06 PM    <DIR>          1.0.0.0__b099876d8fa9b1f3
               0 File(s)              0 bytes

 Directory of C:\windows\assembly\GAC_MSIL\policy.1.0.winfsp-msil\1.0.0.0__b099876d8fa9b1f3

04/12/2017  04:06 PM    <DIR>          .
04/12/2017  04:06 PM    <DIR>          ..
04/12/2017  04:06 PM               443 policy.1.0.winfsp-msil.config
04/12/2017  04:06 PM             3,584 policy.1.0.winfsp-msil.dll
               2 File(s)          4,027 bytes

     Total Files Listed:
               2 File(s)          4,027 bytes
               5 Dir(s)  23,071,674,368 bytes free

C:\Users\billziss\Desktop\passthrough-dotnet-17101>type C:\windows\assembly\GAC_MSIL\policy.1.0.winfsp-msil\1.0.0.0__b099876d8fa9b1f3\policy.1.0.winfsp-msil.config
<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="winfsp-msil" publicKeyToken="b099876d8fa9b1f3" culture="neutral" />
                <bindingRedirect oldVersion="1.0.0.0-1.1.17102.0" newVersion="1.1.17102.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

This problem may be related to .NET Publisher Policy Target Framework


Solution

  • Turns out that the mistake was that the publisher policy was named policy.1.0.winfsp-msil rather than policy.1.1.winfsp-msil.

    To correctly redirect an ASSEMBLY.dll with version MAJOR.MINOR.*.* the policy assembly file must be named policy.MAJOR.MINOR.ASSEMBLY.dll. I.e. the MAJOR.MINOR version must match exactly.