Tuesday 13 May 2014

Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.

Or

Can not execute SQL Server RMO PublicationMonitor TransPendingCommandInfo from a .NET 4.0 application.

or

Load LegacyV2Runtime at runtime

There are a couple of solutions to this issue. The simplest one is to add the following to App.config

xml version="1.0"?>
   
     useLegacyV2RuntimeActivationPolicy="true">    
          version="v4.0" sku=".NETFramework,Version=v4.0"/>  
    


That will allow you application to use Mixed mode assemblies (CLR 2 and 4 in this case).

However, I needed to do this programmatically at runtime as the error was occurring in a reusable user control, so I do not have access to the App.config. To do this, I borrowed the following helper class to load legacy V2 runtime :

public static class RuntimePolicyHelper
{
    public static bool LegacyV2RuntimeEnabledSuccessfully { getprivate set; }
 
    static RuntimePolicyHelper()
    {
        ICLRRuntimeInfo clrRuntimeInfo =
        (ICLRRuntimeInfo)RuntimeEnvironment.GetRuntimeInterfaceAsObject(
        Guid.Empty,
        typeof(ICLRRuntimeInfo).GUID);
        try
        {
            clrRuntimeInfo.BindAsLegacyV2Runtime();
            LegacyV2RuntimeEnabledSuccessfully = true;
        }
        catch (COMException)
        {
            // This occurs with an HRESULT meaning 
            // "A different runtime was already bound to the legacy CLR version 2 activation policy."
            LegacyV2RuntimeEnabledSuccessfully = false;
        }
    }
 
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("BD39D1D2-BA2F-486A-89B0-B4B0CB466891")]
    private interface ICLRRuntimeInfo
    {
        void xGetVersionString();
        void xGetRuntimeDirectory();
        void xIsLoaded();
        void xIsLoadable();
        void xLoadErrorString();
        void xLoadLibrary();
        void xGetProcAddress();
        void xGetInterface();
        void xSetDefaultStartupFlags();
        void xGetDefaultStartupFlags();
 
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void BindAsLegacyV2Runtime();
    }
}
 
 To use this, just call and check the LegacyV2RuntimeEnabledSuccessfully before creating your class. e.g.


if (RuntimePolicyHelper.LegacyV2RuntimeEnabledSuccessfully)
{
     DataAccessConnections.Publisher = _publisher;
 
     _replMonitorHelper = new ReplicationMonitorHelper();
} .....