locked
How can I use a .NET 4.0 assembly in a .NET 2.0 project? (Mixed Mode Assembly problem) RRS feed

  • Question

  • Hi,

    I'm facing the same issue described in this forum thread:

    We are using LEAD TOOLS v15 in our .NET 2.0 solution.

    I have now created a WCF 4.0 client proxy DLL (in .NET 4.0) which I want to use in this solution. When referencing this DLL in our solution, the compiler requires me to convert all the projects which are referencing this DLL from .NET 2.0 to .NET 4.0.

    Unfortunately, after doing so, LEAD TOOLS v15 won't work anymore.

    After adding the useLegacyV2RuntimeActivationPolicy="true" attribute to the <startup> element in the solution's app.config I can circumvent the FileLoadException, but still LEAD TOOLS v15 won't work (as described in the LEAD forum thread mentioned above).

    We are not allowed to update the LEAD TOOLS version in this solution, so...

    I'm wondering whether it is possible for me to still use my .NET 4.0 WCF client proxy DLL in the solution but keeping all the projects set to build against .NET 2.0 CLR?

    I'd very much appreciate if someone please could enlighten me on this.

     


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    • Edited by BetterToday Tuesday, January 24, 2012 4:36 PM
    Tuesday, January 24, 2012 4:30 PM

Answers

  • This manifest thing was too much of investigation for me.

    So I came up with a feasible solution that might do for others as well. Here's the description:


    I have extracted interfaces of my classes and moved them to a separate, new project. Then I set this new interface project to use .NET 2.0 CLR.

    After that I bound my existing .NET 2.0 projects to the interface project and used only the interface definitions as function parameters. This way they could keep being .NET 2.0 projects.



    Our Visual BASIC 6 project uses COM to reference all our .NET 2.0 and .NET 4.0 projects. It's possible in VB6 to use .NET 2.0 and .NET 4.0 in the same process via COM, all of the projects seem to be using their previously assigned CLR version.


    Here's an image of the scenario:


    So, in the .NET 2.0 interface project of [a] we define something like this:

    namespace A.Interface
    {
        [ComVisible(true)]
        public interface IA
        {
            ...
        }
    }


    In the .NET 4.0 class library of [a] we reference the .NET 2.0 interface project and derive a class of it like this:

    using A.Interface;

    namespace A.Implementation
    {
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.AutoDual)]
        public class AImpl : IA
        {
            ...
        }
    }


    Now, in the other .NET 2.0 project, the one that's using a Mixed Mode assembly, we can reference the .NET 2.0 interface project, too, and use the interface types as function parameters:

    using A.Interface;

    namespace B.Implementation
    {
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.AutoDual)]
        public class BImpl
        {
            public void DoSomething(IA someObject)   {...}

            ...
        }
    }

     

    Finally, in the Visual BASIC 6 .config file and in any .NET 4.0 testing application .config file referencing the .NET 2.0 Mixed Mode assembly, we need to add <startup useLegacyV2RuntimeActivationPolicy="true"> to the configuration:

    <?xml version="1.0" encoding="utf-8"?>

    <configuration>

        <configSections>

            <sectionGroup name="applicationSettings" ...>
            </sectionGroup>

            <sectionGroup name="userSettings" ..>
            </sectionGroup>

        </configSections>

        <applicationSettings>
        </applicationSettings>

        <userSettings>
        </userSettings>

        <startup useLegacyV2RuntimeActivationPolicy="true">
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
        </startup>

    </configuration>


    It is very important here that the <configSections> section always comes first in the configuration file if it exists. Otherwise this will result in an obscure configuration exception at program start.

     

    Hopefully my explanation will help anyone else out there facing the same kind of problems.

     


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    • Edited by BetterToday Friday, January 27, 2012 5:54 PM
    • Marked as answer by Paul Zhou Monday, January 30, 2012 5:30 AM
    Friday, January 27, 2012 5:41 PM

All replies

    • Marked as answer by BetterToday Tuesday, January 24, 2012 4:54 PM
    • Unmarked as answer by BetterToday Tuesday, January 24, 2012 5:41 PM
    Tuesday, January 24, 2012 4:38 PM
  • Thanks a lot, Konrad!!!

    That's exactly the information I was striving for.

    I'll give this solution a try right now...


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    Tuesday, January 24, 2012 4:55 PM
  • I just tried the steps described, without creating the manifests but using:
    RegAsm xxx.dll /TLB /CODEBASE /NOLOGO

    While I can use my DLL in Visual BASIC 6, I can't add a COM reference to it in one of my .NET 2.0 projects.

    This is the error message I get using Visual Studio 2010 SP1:

    A reference to 'Test Class' could not be added.

    The ActiveX type library "C:...\TestClass.tlb" was exported from a .NET assembly and can not be added as a reference.

    Add a reference to the .NET assembly instead.


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!


    • Edited by BetterToday Tuesday, January 24, 2012 5:28 PM
    Tuesday, January 24, 2012 5:26 PM
  • I am already on my way home and connot do a research till tomorrow. (Using my phone to write this reply.)

    I am wondering, if you get the same error when you create the tlb with tlbexp.exe.

    All I can promise is that I try to find the time tomorrow to do some tests myself. I have to confess that I never used that myself so far.

    With kind regards,

    Konrad

    Tuesday, January 24, 2012 5:59 PM
  • Thanks, Konrad,

    I appreciate your help.

    In the meantime I'll try to see if using a manifest as described in the blog will get a working solution...

    Thanks,
    Axel

     

     


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    Wednesday, January 25, 2012 11:01 AM
  • Now I have the following problem:

    The only .NET 4.0 type I want to reference in the .NET 2.0 exe file is an abstract class.

    Because it's an abstract class, there is no ProgId in the registry available. Only the interface is there. ... But I don't know how to use/publish this interface in the manifest.

     

     


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    • Edited by BetterToday Wednesday, January 25, 2012 11:58 AM
    Wednesday, January 25, 2012 11:57 AM
  • Hi,

    you only need an abstact class from the .Net 4 assembly? From my understanding, the solution given in the Blog cannot be used for that.

    Is it possible to create a non abstract wrapper around it in .Net 4 so that you could make this available for .Net 2 assemblies through the given way? That is the only workaround I could see at the moment.

    Or why cannot you switch to .Net 4 completly? What are the reasons for that? What errors did you get? Maybe it is easier to solve these issues so you get a "clean" solution again? At the moment I am not aware of any really breaking changes in .Net 4 compared to .Net 2 (except the Workflow Foundation which was rewritten).

    With kind regards,

    Konrad

    Wednesday, January 25, 2012 12:11 PM
  • you only need an abstact class from the .Net 4 assembly? From my understanding, the solution given in the Blog cannot be used for that.

    I was afraid you'd write that...

    Is it possible to create a non abstract wrapper around it in .Net 4 so that you could make this available for .Net 2 assemblies through the given way? That is the only workaround I could see at the moment.

    I have solid classes in the assembly deriving from the base class. But would this work if I'd use one of them but indeed provide an instance of one of the other types? ... Well, they all share the same interface, they only differ in implementation.

    Or why cannot you switch to .Net 4 completly? What are the reasons for that? What errors did you get? Maybe it is easier to solve these issues so you get a "clean" solution again? At the moment I am not aware of any really breaking changes in .Net 4 compared to .Net 2 (except the Workflow Foundation which was rewritten).

    The problem is that I can't update the LEAD Tools version here in the project. LEAD Tools v15 is not compatible with .NET 4.0



    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    • Edited by BetterToday Wednesday, January 25, 2012 2:25 PM
    Wednesday, January 25, 2012 1:12 PM
  • Another question regarding registration-free activation:

     

    What comes next after having added those two manifests to both projects?

    My .NET 4.0 class library resides in directory [a] while my .NET 2.0 Windows Forms executable or class library resides in a different directory [b] plus a different solution.

    How does the executable or the client class library know where to find the DLL file of the .NET 4.0 object?


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    Wednesday, January 25, 2012 5:22 PM
  • Hi,

    I do not have much experience with manifests. So far we registered our COM Components. Once registered, windows knows the component and where to find it through the registry entries that will be created on registration. (regasm /codebase is our call to just register the COM component inside the registry)

    I researched this topic a little and I understood it this way.
    If you want registration free activation of COM components, the COM component must be inside the same directory or a subdirectory of the application that is using the application.
    The most interesting page regarding this topic that I read was:
    http://msdn.microsoft.com/en-us/library/ms973913.aspx

    So if you need to put the components into different locations, then you should check if a simple call to regasm.exe is possible - including the /codebase switch.

    With kind regards,

    Konrad

    Wednesday, January 25, 2012 6:19 PM
  • This manifest thing was too much of investigation for me.

    So I came up with a feasible solution that might do for others as well. Here's the description:


    I have extracted interfaces of my classes and moved them to a separate, new project. Then I set this new interface project to use .NET 2.0 CLR.

    After that I bound my existing .NET 2.0 projects to the interface project and used only the interface definitions as function parameters. This way they could keep being .NET 2.0 projects.



    Our Visual BASIC 6 project uses COM to reference all our .NET 2.0 and .NET 4.0 projects. It's possible in VB6 to use .NET 2.0 and .NET 4.0 in the same process via COM, all of the projects seem to be using their previously assigned CLR version.


    Here's an image of the scenario:


    So, in the .NET 2.0 interface project of [a] we define something like this:

    namespace A.Interface
    {
        [ComVisible(true)]
        public interface IA
        {
            ...
        }
    }


    In the .NET 4.0 class library of [a] we reference the .NET 2.0 interface project and derive a class of it like this:

    using A.Interface;

    namespace A.Implementation
    {
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.AutoDual)]
        public class AImpl : IA
        {
            ...
        }
    }


    Now, in the other .NET 2.0 project, the one that's using a Mixed Mode assembly, we can reference the .NET 2.0 interface project, too, and use the interface types as function parameters:

    using A.Interface;

    namespace B.Implementation
    {
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.AutoDual)]
        public class BImpl
        {
            public void DoSomething(IA someObject)   {...}

            ...
        }
    }

     

    Finally, in the Visual BASIC 6 .config file and in any .NET 4.0 testing application .config file referencing the .NET 2.0 Mixed Mode assembly, we need to add <startup useLegacyV2RuntimeActivationPolicy="true"> to the configuration:

    <?xml version="1.0" encoding="utf-8"?>

    <configuration>

        <configSections>

            <sectionGroup name="applicationSettings" ...>
            </sectionGroup>

            <sectionGroup name="userSettings" ..>
            </sectionGroup>

        </configSections>

        <applicationSettings>
        </applicationSettings>

        <userSettings>
        </userSettings>

        <startup useLegacyV2RuntimeActivationPolicy="true">
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
        </startup>

    </configuration>


    It is very important here that the <configSections> section always comes first in the configuration file if it exists. Otherwise this will result in an obscure configuration exception at program start.

     

    Hopefully my explanation will help anyone else out there facing the same kind of problems.

     


    Vote here for a Microsoft Connect feedback channel on Windows - and win a better Windows!

    • Edited by BetterToday Friday, January 27, 2012 5:54 PM
    • Marked as answer by Paul Zhou Monday, January 30, 2012 5:30 AM
    Friday, January 27, 2012 5:41 PM
  • Thank you for sharing your solution here. It will be very beneficial for other community members who have similar questions.

     

    Have a nice day!


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Monday, January 30, 2012 5:29 AM