Visual Studio 2010 has a new feature, Embed Interop Types, that can simplify application deployment and solve those pesky issues that can arise when using COM Interop and Primary Interop Assemblies (PIAs). If you’ve ever had to ship multiple versions of an application that automates Microsoft Office where the only difference between your published versions is the version of the PIA (to match different Office versions), then this feature is for you.
You enable type embedding when you reference an assembly. In Visual Studio, you set the Embed Interop Types property to true (the default). The command-line compiler equivalent is the new /link compiler option. You can read all about the feature here: /link compiler option (C#), /link compiler option (VB).
There are also a couple of examples available in the help documentation:
- Walkthrough: Embedding Type Information from Microsoft Office Assemblies (C# and Visual Basic)
- Walkthrough: Embedding Types from Managed Assemblies (C# and Visual Basic) (it’s not just for COM Interop)
When you embed type information, you can run into some confusing errors. Here are the most common errors and information on the cause and resolution.
VBC40059 (VB), CS1762 (C#)
A reference was created to embedded interop assembly ‘<assembly1>’ because of an indirect reference to that assembly from assembly ‘<assembly2>’
This error can surprise you. Because type the Embed Interop Types property is set to true by default, you are embedding type information and may not realize it. This error will occur when you have references to two different assemblies. For the first assembly reference, you have set the Embed Interop Types property to True. For the second you have set the Embed Interop Types property to False. The error occurs in this case because the second assembly also references the first assembly. Now you have a situation where your application instructs the compiler to both embed type information from the first assembly, and to not embed type information from the first assembly, via the second assembly.
To resolve the issue, you need to set the Embed Interop Types property for both assembly references to the same value; true to embed type information, false to get type information from the PIA.
VBC 31539 (VB), CS1748 (C#)
Cannot find the interop type that matches the embedded interop type ‘<type>’. Are you missing an assembly reference?
This method is similar to the previous error in that it occurs if one assembly embeds type information and another does not. In this case, you have an assembly, assembly1, that references a PIA assembly with Embed Interop Types is set to true. Assembly1 then exposes a type from the PIA assembly, for example as the return type from a method or property. Another assembly, assembly2, references assembly1 and makes use of the embedded type. The error occurs if assembly2 does not also reference the PIA assembly, and therefore cannot locate the embedded type information.
To resolve the issue, you need to add a reference from the second assembly to the PIA assembly and set the Embed Interop Types property to true. Thus, both assemblies will have a reference to the PIA assembly, with type information embedded, and both can utilize the embedded type.
VBC36924 (VB), CS1772 (C#)
Type ‘<type>’ cannot be used across assembly boundaries because a type in its inheritance hierarchy has a generic type parameter that is an embedded interop type.
This error occurs in the same scenario as VBC 31539 (VB) and CS1748 (C#). You have an assembly, assembly1, that references an assembly with Embed Interop Types is set to true. Assembly1 then exposes a type and another assembly, assembly2, utilizes the exposed type. The error occurs if the type that is exposed is a generic, and the generic parameter is of an embedded type.
Unfortunately, this is a limitation of the Common Language Runtime (CLR). If you are able to, you can resolve the issue by modifying the assembly that exposes the embedded type as a generic parameter. You can either modify the references to the PIA assembly to set Embed Interop Types to false and thus reference that PIA assembly that contains the COM type information. Or, as the author of the library you can expose an interface with an embedded type as a generic parameter. For example, if you encounter this error when calling a method that returns a generic list such as List(Of Excel.Application) (in C# List<Excel.Application>), then you could resolve the issue by modifying the method to return IList(Of Excel.Application) (in C# IList< Excel.Application >).