locked
Interop Reference vs COM Reference RRS feed

  • Question

  • I understand that interop assemblies can be built by .net and one should use PIAs but I've noticed that I can reference an Interop assembly or reference the COM assembly directly. It terms of coding it doesn't seem to make a difference however the references do look different in the project file:

    Direct reference:

    <ItemGroup>
        <COMReference Include="ABCLib">
          <Guid>{0D52BS34-109B-4456-AC02-B869CD33EBS4}</Guid>
          <VersionMajor>1</VersionMajor>
          <VersionMinor>0</VersionMinor>
          <Lcid>0</Lcid>
          <WrapperTool>tlbimp</WrapperTool>
          <Isolated>False</Isolated>
        </COMReference>
      </ItemGroup>

    Interop reference:

    <Reference Include="Interop.ABCLib, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />

    If the referenced interop assembly is one that's been generated by tlbimp is there any difference between the above 2 methods? I assume not since the COMReference has that <WrapperTool>tlbimp</WrapperTool> tag which I imagine means that it will generate the Interop assembly when required?

    Tuesday, April 12, 2011 7:47 AM

Answers

  • Hello ploxis,

     

    >> If the referenced interop assembly is one that's been generated by tlbimp is there any difference between the above 2 methods? I assume not since the COMReference has that <WrapperTool>tlbimp</WrapperTool> tag which I imagine means that it will generate the Interop assembly when required?

    I'm not sure how to go about answering this so I decided to present an overall big picture of interop assemblies in general and expound on the special purpose behind a PIA. I hope that with better insight you will be better equipped to make the appropriate decisions.

     

    1. Three Types of Interop Assemblies.

    In actual fact, you are talking about 3 types of interop assemblies :

    1.1 An interop assembly that a developer creates by himself/herself on a COM type library via tlbimp.exe.

    1.1.1 Such an interop assembly is not necessarily a Primary Interop Assembly.

    1.1.2 To qualify it as a PIA, see point 1.3 below.

     

    1.2 An interop assembly that the Visual Studio generates on behalf of the developer when the developer references a COM type library directly (either a DLL or a TLB).

    1.2.1 Such an interop assembly is not a Primary Interop Assembly.

     

    1.3 An interop assembly that a developer creates by himself/herself on a COM type library via tlbimp.exe with a strong name key file and the /primary flag.

    1.3.1 Such an interop assembly is a Primary Interop Assembly.

    1.3.2 To be really useful, this PIA must be registered to the registry via regasm.exe.

    1.3.3 To be even more meaningful in purpose, this PIA should be registered to the GAC.

    Once the PIA is registered to the registry (via regasm.exe), if tlbimp.exe is called again on the same COM type library with a strong name key file and the /primary flag, a warning will be issued by tlbimp.exe indicating that a PIA for the type library has already been created and registered. Note however, that the interop assembly will still be created nevertheless. But one should heed this warning and not proceed to create another PIA. Defying this warning will defeat the purpose of a PIA.

    Although there is no necessity to install a PIA to the GAC, it is betrer to do so in line with good practice. After all, it makes no sense to have many copies of a PIA in a machine when they all refer to the same types. Note that it is the strong name key contained inside the PIA that makes the types that the PIA contains unique no matter how many copies of a PIA there are in a machine.

    Content-wise, a PIA is no different from a equivalent non-primary interop assembly. Besides being digitally signed it is internally marked with a PIA-specific custom attribute (System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute). You can see this attribute by using ildasm.exe to examine the PIA's metadata.

     

    2. The Crucial Difference Between COM and .NET in terms of Type Identity.

    2.1 Before going any further, I need to expound on the crucial difference in the definition of identity between COM and the .NET Framework :

    2.1.1 In COM, a type is solely identified by its GUID. As long as the GUID is the same, it is the same type.

    2.1.2 In the .NET Framework, a type's containing assembly forms part of the type's identity. This implies that the assembly's name, version, culture and public/private key pair matters.

    2.2 Now as far as the .NET Framework is concerned, the COM types contained inside an interop assembly are each represented by an equivalent managed type. And each managed type is indelibly bound to its containing assembly. Hence if we have 2 interop assemblies for the same type library, the COM types contained inside each could potentially be different types as far as the CLR is concerned.

    2.3 If x number of assemblies each references its own interop assembly, we could have a situation where x number of interop assemblies are each indispensible with each assembly being able to use only the types from its own interop assembly. This is truly undesireable because the interop assemblies are all generated from the same COM type library.

    2.4 This is the heart of the problem that a PIA is designed to resolve. A PIA is meant to be generated (and digitally signed) once by the developer of the original COM component and deployed multiple times by client applications.

    2.5 Let me explain the problem via some examples given in section 3 below.

     

    3. Example Scenarios.

    3.1 Take, for example, the following scenario :

    3.1.1 A developer creates 2 class libraries. The 2 class libs are not strong named.

    3.1.2 Each class lib references a common COM type library via the IDE. Hence each class lib has its own IDE-generated interop assembly for the COM type library.

    3.1.3 A managed main application references both class libs and makes a local copy of each class lib in its folder.

    3.1.4 Now because each class lib references its own interop assembly and both interop assemblies have the same name, eventually only one interop assembly gets copied to the main app's folder.

    3.1.5 At runtime everything usually works out correctly. It worked out correctly because each class lib referred to the same interop assembly with the same name, version and culture. No public key tokens are compared.

     

    3.2 Now take a different approach to the above scenario :

    3.2.1 This time. the developer strong names each class lib.

    3.2.2 The IDE will likewise strong name each class lib's interop assembly with the respective class lib's key pair.

    3.2.3 This time, the two interop assemblies are no longer identical. They are different in their digital signatures.

    3.2.4 When the class libs are referenced by a main client application, only one interop assembly will be copied to the client application's folder since the interop assemblies have the same name even though they are different as far as .NET is concerned.

    3.2.5 Then at runtime, System.IO.FileLoadException will occur because one of the interop assemblies (with a specific public key token) will not be found.

    3.2.6 The only way out of this problem would be to install both class libraries and each of their interop assemblies (4 files in total) into the GAC.

     

    3.3 I hope you will see how the examples in 3.1 and 3.2 illustrate the usefulness of a PIA :

    3.3.1 Being already digitally signed with a strong name key pair, a PIA's identity remains the same no matter how many clients references it. This means that the (COM) types that it contains will get used by all referencing managed assemblies.

    3.3.2 In fact, if a PIA gets installed into the GAC, client applications need not even bother to retain a copy of it in their main folder.

     

    4. In Summary.

    4.1 As to the question of whether there is a difference between referencing a COM type library or referencing an interop assembly, my answer would be : potentially yes.

    4.2 One factor to consider is whether the type library is referenced by more than one assembly and whether there is a need to strong name any of the assemblies.

    4.3 In the simple case where the referencing assemblies are never strong named (as in the case of example 3.1), there should be no problems in locally sharing a common interop assembly.

    4.4 But in line with good practice, it is always a good idea to generate a digitally signed PIA and install it into the GAC and have all assemblies reference this central PIA.

     

    - Bio.

     


    • Marked as answer by Paul Zhou Wednesday, April 20, 2011 2:30 AM
    Monday, April 18, 2011 7:17 PM
  • A PIA might have been modified by the vendor in some way, but the end result should be pretty much the same.
    Mattias, C# MVP
    • Marked as answer by Paul Zhou Wednesday, April 20, 2011 2:30 AM
    Tuesday, April 12, 2011 1:05 PM
  •  

    Like any other managed assembly, an interop assembly is a collection of types that are deployed, versioned, and configured as a single unit. However, unlike other managed assemblies, an interop assembly contains type definitions (not implementation) of types that have already been defined in COM. These type definitions allow managed applications to bind to the COM types at compile time and provide information to the common language runtime about how the types should be marshaled at run time.

     

    Primary Interop Assemblies (PIAs)


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Paul Zhou Wednesday, April 20, 2011 2:30 AM
    Monday, April 18, 2011 6:55 AM

All replies

  • A PIA might have been modified by the vendor in some way, but the end result should be pretty much the same.
    Mattias, C# MVP
    • Marked as answer by Paul Zhou Wednesday, April 20, 2011 2:30 AM
    Tuesday, April 12, 2011 1:05 PM
  •  

    Like any other managed assembly, an interop assembly is a collection of types that are deployed, versioned, and configured as a single unit. However, unlike other managed assemblies, an interop assembly contains type definitions (not implementation) of types that have already been defined in COM. These type definitions allow managed applications to bind to the COM types at compile time and provide information to the common language runtime about how the types should be marshaled at run time.

     

    Primary Interop Assemblies (PIAs)


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Paul Zhou Wednesday, April 20, 2011 2:30 AM
    Monday, April 18, 2011 6:55 AM
  • Hello ploxis,

     

    >> If the referenced interop assembly is one that's been generated by tlbimp is there any difference between the above 2 methods? I assume not since the COMReference has that <WrapperTool>tlbimp</WrapperTool> tag which I imagine means that it will generate the Interop assembly when required?

    I'm not sure how to go about answering this so I decided to present an overall big picture of interop assemblies in general and expound on the special purpose behind a PIA. I hope that with better insight you will be better equipped to make the appropriate decisions.

     

    1. Three Types of Interop Assemblies.

    In actual fact, you are talking about 3 types of interop assemblies :

    1.1 An interop assembly that a developer creates by himself/herself on a COM type library via tlbimp.exe.

    1.1.1 Such an interop assembly is not necessarily a Primary Interop Assembly.

    1.1.2 To qualify it as a PIA, see point 1.3 below.

     

    1.2 An interop assembly that the Visual Studio generates on behalf of the developer when the developer references a COM type library directly (either a DLL or a TLB).

    1.2.1 Such an interop assembly is not a Primary Interop Assembly.

     

    1.3 An interop assembly that a developer creates by himself/herself on a COM type library via tlbimp.exe with a strong name key file and the /primary flag.

    1.3.1 Such an interop assembly is a Primary Interop Assembly.

    1.3.2 To be really useful, this PIA must be registered to the registry via regasm.exe.

    1.3.3 To be even more meaningful in purpose, this PIA should be registered to the GAC.

    Once the PIA is registered to the registry (via regasm.exe), if tlbimp.exe is called again on the same COM type library with a strong name key file and the /primary flag, a warning will be issued by tlbimp.exe indicating that a PIA for the type library has already been created and registered. Note however, that the interop assembly will still be created nevertheless. But one should heed this warning and not proceed to create another PIA. Defying this warning will defeat the purpose of a PIA.

    Although there is no necessity to install a PIA to the GAC, it is betrer to do so in line with good practice. After all, it makes no sense to have many copies of a PIA in a machine when they all refer to the same types. Note that it is the strong name key contained inside the PIA that makes the types that the PIA contains unique no matter how many copies of a PIA there are in a machine.

    Content-wise, a PIA is no different from a equivalent non-primary interop assembly. Besides being digitally signed it is internally marked with a PIA-specific custom attribute (System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute). You can see this attribute by using ildasm.exe to examine the PIA's metadata.

     

    2. The Crucial Difference Between COM and .NET in terms of Type Identity.

    2.1 Before going any further, I need to expound on the crucial difference in the definition of identity between COM and the .NET Framework :

    2.1.1 In COM, a type is solely identified by its GUID. As long as the GUID is the same, it is the same type.

    2.1.2 In the .NET Framework, a type's containing assembly forms part of the type's identity. This implies that the assembly's name, version, culture and public/private key pair matters.

    2.2 Now as far as the .NET Framework is concerned, the COM types contained inside an interop assembly are each represented by an equivalent managed type. And each managed type is indelibly bound to its containing assembly. Hence if we have 2 interop assemblies for the same type library, the COM types contained inside each could potentially be different types as far as the CLR is concerned.

    2.3 If x number of assemblies each references its own interop assembly, we could have a situation where x number of interop assemblies are each indispensible with each assembly being able to use only the types from its own interop assembly. This is truly undesireable because the interop assemblies are all generated from the same COM type library.

    2.4 This is the heart of the problem that a PIA is designed to resolve. A PIA is meant to be generated (and digitally signed) once by the developer of the original COM component and deployed multiple times by client applications.

    2.5 Let me explain the problem via some examples given in section 3 below.

     

    3. Example Scenarios.

    3.1 Take, for example, the following scenario :

    3.1.1 A developer creates 2 class libraries. The 2 class libs are not strong named.

    3.1.2 Each class lib references a common COM type library via the IDE. Hence each class lib has its own IDE-generated interop assembly for the COM type library.

    3.1.3 A managed main application references both class libs and makes a local copy of each class lib in its folder.

    3.1.4 Now because each class lib references its own interop assembly and both interop assemblies have the same name, eventually only one interop assembly gets copied to the main app's folder.

    3.1.5 At runtime everything usually works out correctly. It worked out correctly because each class lib referred to the same interop assembly with the same name, version and culture. No public key tokens are compared.

     

    3.2 Now take a different approach to the above scenario :

    3.2.1 This time. the developer strong names each class lib.

    3.2.2 The IDE will likewise strong name each class lib's interop assembly with the respective class lib's key pair.

    3.2.3 This time, the two interop assemblies are no longer identical. They are different in their digital signatures.

    3.2.4 When the class libs are referenced by a main client application, only one interop assembly will be copied to the client application's folder since the interop assemblies have the same name even though they are different as far as .NET is concerned.

    3.2.5 Then at runtime, System.IO.FileLoadException will occur because one of the interop assemblies (with a specific public key token) will not be found.

    3.2.6 The only way out of this problem would be to install both class libraries and each of their interop assemblies (4 files in total) into the GAC.

     

    3.3 I hope you will see how the examples in 3.1 and 3.2 illustrate the usefulness of a PIA :

    3.3.1 Being already digitally signed with a strong name key pair, a PIA's identity remains the same no matter how many clients references it. This means that the (COM) types that it contains will get used by all referencing managed assemblies.

    3.3.2 In fact, if a PIA gets installed into the GAC, client applications need not even bother to retain a copy of it in their main folder.

     

    4. In Summary.

    4.1 As to the question of whether there is a difference between referencing a COM type library or referencing an interop assembly, my answer would be : potentially yes.

    4.2 One factor to consider is whether the type library is referenced by more than one assembly and whether there is a need to strong name any of the assemblies.

    4.3 In the simple case where the referencing assemblies are never strong named (as in the case of example 3.1), there should be no problems in locally sharing a common interop assembly.

    4.4 But in line with good practice, it is always a good idea to generate a digitally signed PIA and install it into the GAC and have all assemblies reference this central PIA.

     

    - Bio.

     


    • Marked as answer by Paul Zhou Wednesday, April 20, 2011 2:30 AM
    Monday, April 18, 2011 7:17 PM