My background in technical support had likely resulted in me putting far too much information in this post, leading to nobody being interested in reading it, but IMHO, more information is better than less.
There is something very basic and fundamental about assembly binding and redirection that I'm missing. I'm trying to create a policy DLL to redirect applications that have compiled against an older version of my assembly to the newest version. Nothing I do seems to work. I've outlined the steps I take below. I'm not using Visual Studio, but just the command line tools included with the .NET Framework and the Windows SDK. Can anybody tell me why, in step eleven, when I run the application that was compiled against the v1.0.0 version of my assembly, that the application is not redirected towards the v2.0.0 assembly that is registered in the GAC?
As you follow along what I did, you'll often have to take note of the directory I've executed commands in.
I would be more than happy with an RTFM answer, if you'd just be so kind as to point to TFM I'm supposed to read.
Thanks in advance, Reg
c:\stackexchangetest> sn -k stackTest.snk
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Key pair written to stackTest.snk
c:\stackexchangetest> sn -p stackTest.snk publicStackTest.snk
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Public key written to publicStackTest.snk
c:\stackexchangetest> sn -tp publicStackTest.snk
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Public key is
002400000480000094000000060200000024000052534131000400000100010079ba0ab991ceda
d7ba4a767d55889a6cd0eafc9bc15c394620b61c02f4c1112dd9e348cbb4826775c72164ac8552
f9b751b1a1dd71874c04b24221f00f4ee8c2971f3ac8b6b381b26d39cbd3347e773bf08e9af838
6d7f317592951a4985e2c187288d037d5af2f62cce2e4dc700d0d00feb4c095df5d12c9a0908dc
8606cdad
Public key token is 6dfd37060fccec62
c:\stackexchangetest\1.0.0> type StackTest.cs
using System;
namespace stack.exchange.rdomarat
{
public class stackTest
{
public static String getVersion()
{
return( "1.0.0" );
}
}
}
c:\stackexchangetest\1.0.0> type AssemblyInfo.cs
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("stack.exchange.rdomarat")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("StackExchange")]
[assembly: AssemblyProduct("rdomarat")]
[assembly: AssemblyCopyright("Copyright 2012")]
[assembly: AssemblyTrademark("rdomarat")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("a3d17815-97f5-4e56-803c-06f652a23369")]
[assembly: AssemblyVersion( "1.0.0" )]
c:\stackexchangetest\1.0.0> csc /out:stack.exchange.rdomarat.dll /keyfile:../stackTest.snk /debug /w:4 /t:library AssemblyInfo.cs StackTest.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.5420
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
c:\stackexchangetest\1.0.0> type stack.exchange.rdomarat.config
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="stack.exchange.rdomarat"
publicKeyToken="6dfd37060fccec62"
culture=neutral
/>
<bindingRedirect oldVersion="1.0.0-1.0.0"
newVersion="1.0.0"
/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
c:\stackexchangetest\1.0.0> al.exe /version:1.0.0 /link:stack.exchange.rdomarat.config /out:policy.1.0.stack.exchange.rdomarat.dll /keyfile:../stackTest.snk /description:"Policy file" /title:"Policy file" /company:"StackExchange" /copyright:"Copyright 2012" /trademark:"rdomarat" /product:"rdomarat"
Microsoft (R) Assembly Linker version 9.0.30729.1
Copyright (C) Microsoft Corporation. All rights reserved.
c:\stackexchangetest\1.0.0> gacutil -u stack.exchange.rdomarat
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
No assemblies found matching: stack.exchange.rdomarat
Number of assemblies uninstalled = 0
Number of failures = 0
c:\stackexchangetest\1.0.0> gacutil -u policy.1.0.stack.exchange.rdomarat
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
No assemblies found matching: policy.1.0.stack.exchange.rdomarat
Number of assemblies uninstalled = 0
Number of failures = 0
c:\stackexchangetest\1.0.0> gacutil -i stack.exchange.rdomarat.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
c:\stackexchangetest\1.0.0> gacutil -i policy.1.0.stack.exchange.rdomarat.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
c:\stackexchangetest\stackapp\1.0.0> type stackApp.cs
using System;
using stack.exchange.rdomarat;
public class StackApp
{
public static void Main()
{
String s1;
s1 = stackTest.getVersion();
Console.WriteLine("Hello " + s1);
}
}
c:\stackexchangetest\stackapp\1.0.0> csc /out:StackApp.exe /target:exe /reference:..\..\1.0.0\stack.exchange.rdomarat.dll StackApp.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.5420
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
c:\stackexchangetest\stackapp\1.0.0> stackapp
Hello 1.0.0
c:\stackexchangetest\2.0.0> type StackTest.cs
using System;
namespace stack.exchange.rdomarat
{
public class stackTest
{
public static String getVersion()
{
return( "2.0.0" );
}
}
}
c:\stackexchangetest\2.0.0> type AssemblyInfo.cs
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("stack.exchange.rdomarat")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("StackExchange")]
[assembly: AssemblyProduct("rdomarat")]
[assembly: AssemblyCopyright("Copyright 2012")]
[assembly: AssemblyTrademark("rdomarat")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("a3d17815-97f5-4e56-803c-06f652a23369")]
[assembly: AssemblyVersion( "2.0.0" )]
c:\stackexchangetest\2.0.0> csc /out:stack.exchange.rdomarat.dll /keyfile:../stackTest.snk /debug /w:4 /t:library AssemblyInfo.cs StackTest.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.5420
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
c:\stackexchangetest\2.0.0> type stack.exchange.rdomarat.config
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="stack.exchange.rdomarat"
publicKeyToken="6dfd37060fccec62"
culture=neutral
/>
<bindingRedirect oldVersion="1.0.0-2.0.0"
newVersion="2.0.0"
/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
c:\stackexchangetest\2.0.0> al.exe /version:2.0.0 /link:stack.exchange.rdomarat.config /out:policy.2.0.stack.exchange.rdomarat.dll /keyfile:../stackTest.snk /description:"Policy file" /title:"Policy file" /company:"StackExchange" /copyright:"Copyright 2012" /trademark:"rdomarat" /product:"rdomarat"
Microsoft (R) Assembly Linker version 9.0.30729.1
Copyright (C) Microsoft Corporation. All rights reserved.
c:\stackexchangetest\2.0.0> gacutil -u policy.2.0.stack.exchange.rdomarat
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
No assemblies found matching: policy.2.0.stack.exchange.rdomarat
Number of assemblies uninstalled = 0
Number of failures = 0
c:\stackexchangetest\2.0.0> gacutil -i stack.exchange.rdomarat.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
c:\stackexchangetest\2.0.0> gacutil -i policy.2.0.stack.exchange.rdomarat.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
c:\stackexchangetest\stackapp\2.0.0> type stackApp.cs
using System;
using stack.exchange.rdomarat;
public class StackApp
{
public static void Main()
{
String s1;
s1 = stackTest.getVersion();
Console.WriteLine("Hello " + s1);
}
}
c:\stackexchangetest\stackapp\2.0.0> csc /out:StackApp.exe /target:exe /reference:..\..\2.0.0\stack.exchange.rdomarat.dll StackApp.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.5420
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
c:\stackexchangetest\stackapp\2.0.0> StackApp.exe
Hello 2.0.0
c:\stackexchangetest\stackapp\2.0.0> gacutil -u policy.2.0.stack.exchange.rdomarat
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly: policy.2.0.stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral,PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Uninstalled: policy.2.0.stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Number of assemblies uninstalled = 1
Number of failures = 0
c:\stackexchangetest\stackapp\2.0.0> gacutil -u policy.1.0.stack.exchange.rdomarat
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly: policy.1.0.stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral,PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Uninstalled: policy.1.0.stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Number of assemblies uninstalled = 1
Number of failures = 0
c:\stackexchangetest\stackapp\2.0.0> gacutil -u stack.exchange.rdomarat
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly: stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Uninstalled: stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Assembly: stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Uninstalled: stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62, processorArchitecture=MSIL
Number of assemblies uninstalled = 2
Number of failures = 0
c:\stackexchangetest\stackapp\1.0.0> StackApp.exe
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62' or one of its dependencies. The system cannot find the file specified.
File name: 'stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62' at StackApp.Main()
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
Running under executable c:\StackExchangeTest\StackApp\1.0.0\StackApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = SYBASE\rdomarat
LOG: DisplayName = stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62 (Fully-specified)
LOG: Appbase = file:///C:/Users/rdomarat/Documents/Issues/111205_mlclient_policy/StackExchangeTest/StackApp/1.0.0/
LOG: Initial PrivatePath = NULL
Calling assembly : StackApp, 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 machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62
LOG: The same bind was seen before, and was failed with hr = 0x80070002.
c:\stackexchangetest\stackapp\2.0.0> StackApp.exe
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62' or one of its dependencies. The system cannot find the file specified.
File name: 'stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62' at StackApp.Main()
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
Running under executable c:\StackExchangeTest\StackApp\2.0.0\StackApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = SYBASE\rdomarat
LOG: DisplayName = stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62 (Fully-specified)
LOG: Appbase = file:///C:/Users/rdomarat/Documents/Issues/111205_mlclient_policy/StackExchangeTest/StackApp/2.0.0/
LOG: Initial PrivatePath = NULL
Calling assembly : StackApp, 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 machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: stack.exchange.rdomarat, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62
LOG: The same bind was seen before, and was failed with hr = 0x80070002.
c:\stackexchangetest\2.0.0> gacutil -i stack.exchange.rdomarat.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
c:\stackexchangetest\2.0.0> gacutil -i policy.2.0.stack.exchange.rdomarat.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
c:\stackexchangetest\stackapp\2.0.0> StackApp.exe
Hello 2.0.0
c:\stackexchangetest\stackapp\1.0.0> StackApp.exe
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62' or one of its dependencies. The system cannot find the file specified.
File name: 'stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62' at StackApp.Main()
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
Running under executable c:\StackExchangeTest\StackApp\1.0.0\StackApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = SYBASE\rdomarat
LOG: DisplayName = stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62 (Fully-specified)
LOG: Appbase = file:///C:/Users/rdomarat/Documents/Issues/111205_mlclient_policy/StackExchangeTest/StackApp/1.0.0/
LOG: Initial PrivatePath = NULL
Calling assembly : StackApp, 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 machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: stack.exchange.rdomarat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6dfd37060fccec62
LOG: The same bind was seen before, and was failed with hr = 0x80070002.
Turns out my whole problem from day one was the lack of double quotes around :
culture=neutral
I change the .config file to read
culture="neutral"
and everything worked like a charm. An error in the assembly binding debug outlog log that indicated a parse error in the XML for the config file would have been handy, and might have saved me two days. Oh well.