locked
Set Embed Interop Type programmatically RRS feed

  • Question

  • How can I set the Embed Interop Type of a reference programmatically? I am adding references in an item template and would like to set this property to false in my item template wizard code. I've found the VSProjReferencePropId100 enum with a member DISPID_Reference_EmbedInteropTypes but do you know how can I use it in with an VSLangProj80.Reference3 object?

    Thanks!


    sorpor
    Wednesday, October 6, 2010 7:48 PM

Answers

  • Hi Sorpor,

    For some reason it appears the new interfaces didn't get incorporated into the VSLangProj100.dll interop assembly. If you review the VSLangProj100.idl you'll see there are some additional interfaces like Reference4 (with the EmbedInteropTypes property), and a few others like CSharpProjectConfigurationProperties5, and CSharpProjectProperties6 for example.

    The DISPID_Reference_EmbedInteropTypes is just the dispatch ID used to identify the property. Apart from telling us the dispatch ID is 127, it's not of much use.

    I'll get a bug in, to see if we can get this fixed. In the meantime, you can work around this by declaring and using your own Reference4 interface as follows. Note, Reference4 inherits from Reference3, and Reference3 inherits from Reference2, etc. So we need to list all the properties. The interface guid for Reference4 can be found in the VSLangProj100.idl, and you can pretty much copy the implementation by viewing the metadata for the earlier interfaces (by way of the "Go to Definition" (F12) command).

        [Guid("5021602E-2025-4299-88D2-0A92E8B41ADF")]
        public interface Reference4
        {
            // Reference
            [DispId(1)] DTE DTE { get; }
            [DispId(2)] References Collection { get; }
            [DispId(3)] Project ContainingProject { get; }
            [DispId(4)] void Remove();
            [DispId(5)] string Name { get; }
            [DispId(6)] prjReferenceType Type { get; }
            [DispId(7)] string Identity { get; }
            [DispId(8)] string Path { get; }
            [DispId(9)] string Description { get; }
            [DispId(10)] string Culture { get; }
            [DispId(11)] int MajorVersion { get; }
            [DispId(12)] int MinorVersion { get; }
            [DispId(13)] int RevisionNumber { get; }
            [DispId(14)] int BuildNumber { get; }
            [DispId(15)] bool StrongName { get; }
            [DispId(16)] Project SourceProject { get; }
            [DispId(17)] bool CopyLocal { getset; }
            [DispId(18), TypeLibFunc(1088)] dynamic get_Extender(string ExtenderName);
            [DispId(19)] dynamic ExtenderNames { get; }
            [DispId(20)] string ExtenderCATID { get; }
            [DispId(21)] string PublicKeyToken { get; }
            [DispId(22)] string Version { get; }

            // Reference2
            [DispId(100)]string RuntimeVersion { get; }

            // Reference3
            [DispId(120)] bool SpecificVersion { getset; }
            [DispId(121)] string SubType { getset; }
            [DispId(122)] bool Isolated { getset; }
            [DispId(123)] string Aliases { getset; }
            [DispId(124)] uint RefType { get; }
            [DispId(125)] bool AutoReferenced { get; }
            [DispId(126)] bool Resolved { get; }

            // Reference4
            [DispId(127)] bool EmbedInteropTypes { getset; }
        }
                Project proj = _applicationObject.Solution.Projects.Item(1);
                VSProject vsProj = (VSProject)proj.Object;
                Reference4 firstRef = vsProj.References.Item(1) as Reference4;
                firstRef.EmbedInteropTypes = true;

    Sincerely,


    Ed Dore
    Wednesday, October 13, 2010 5:48 PM
  • I finally got it working. The GUID 5021602E-2025-4299-88D2-0A92E8B41ADF on the interface is wrong. This is the GUID from the Reference3 interface.

    The correct one is F71B6036-80F1-4F08-BC59-B5D92865F629. This could be checked using the OLE/COM Object Viewer.

    For some reason the wrong GUID works on the main thread but not on a different worker thread.

    The correct interface should be:

    [Guid("F71B6036-80F1-4F08-BC59-B5D92865F629")]
      public interface Reference4
      {    
        // Reference    
        [DispId(1)] DTE DTE { get; }    
        [DispId(2)] References Collection { get; }    
        [DispId(3)] Project ContainingProject { get; }    
        [DispId(4)] void Remove();    
        [DispId(5)] string Name { get; }    
        [DispId(6)] prjReferenceType Type { get; }    
        [DispId(7)] string Identity { get; }    
        [DispId(8)] string Path { get; }    
        [DispId(9)] string Description { get; }    
        [DispId(10)] string Culture { get; }    
        [DispId(11)] int MajorVersion { get; }    
        [DispId(12)] int MinorVersion { get; }    
        [DispId(13)] int RevisionNumber { get; }    
        [DispId(14)] int BuildNumber { get; }    
        [DispId(15)] bool StrongName { get; }    
        [DispId(16)] Project SourceProject { get; }    
        [DispId(17)] bool CopyLocal { get; set; }    
        [DispId(18), TypeLibFunc(1088)] dynamic get_Extender(string ExtenderName);    
        [DispId(19)] dynamic ExtenderNames { get; }    
        [DispId(20)] string ExtenderCATID { get; }    
        [DispId(21)] string PublicKeyToken { get; }    
        [DispId(22)] string Version { get; }     
        // Reference2    
        [DispId(100)]string RuntimeVersion { get; }     
        // Reference3    
        [DispId(120)] bool SpecificVersion { get; set; }    
        [DispId(121)] string SubType { get; set; }    
        [DispId(122)] bool Isolated { get; set; }    
        [DispId(123)] string Aliases { get; set; }    
        [DispId(124)] uint RefType { get; }    
        [DispId(125)] bool AutoReferenced { get; }   
        [DispId(126)] bool Resolved { get; }    
        // Reference4    
        [DispId(127)] bool EmbedInteropTypes { get; set; }  
      }
    

    Saturday, May 21, 2011 3:29 PM

All replies

  • Hi Sorpor,

    For some reason it appears the new interfaces didn't get incorporated into the VSLangProj100.dll interop assembly. If you review the VSLangProj100.idl you'll see there are some additional interfaces like Reference4 (with the EmbedInteropTypes property), and a few others like CSharpProjectConfigurationProperties5, and CSharpProjectProperties6 for example.

    The DISPID_Reference_EmbedInteropTypes is just the dispatch ID used to identify the property. Apart from telling us the dispatch ID is 127, it's not of much use.

    I'll get a bug in, to see if we can get this fixed. In the meantime, you can work around this by declaring and using your own Reference4 interface as follows. Note, Reference4 inherits from Reference3, and Reference3 inherits from Reference2, etc. So we need to list all the properties. The interface guid for Reference4 can be found in the VSLangProj100.idl, and you can pretty much copy the implementation by viewing the metadata for the earlier interfaces (by way of the "Go to Definition" (F12) command).

        [Guid("5021602E-2025-4299-88D2-0A92E8B41ADF")]
        public interface Reference4
        {
            // Reference
            [DispId(1)] DTE DTE { get; }
            [DispId(2)] References Collection { get; }
            [DispId(3)] Project ContainingProject { get; }
            [DispId(4)] void Remove();
            [DispId(5)] string Name { get; }
            [DispId(6)] prjReferenceType Type { get; }
            [DispId(7)] string Identity { get; }
            [DispId(8)] string Path { get; }
            [DispId(9)] string Description { get; }
            [DispId(10)] string Culture { get; }
            [DispId(11)] int MajorVersion { get; }
            [DispId(12)] int MinorVersion { get; }
            [DispId(13)] int RevisionNumber { get; }
            [DispId(14)] int BuildNumber { get; }
            [DispId(15)] bool StrongName { get; }
            [DispId(16)] Project SourceProject { get; }
            [DispId(17)] bool CopyLocal { getset; }
            [DispId(18), TypeLibFunc(1088)] dynamic get_Extender(string ExtenderName);
            [DispId(19)] dynamic ExtenderNames { get; }
            [DispId(20)] string ExtenderCATID { get; }
            [DispId(21)] string PublicKeyToken { get; }
            [DispId(22)] string Version { get; }

            // Reference2
            [DispId(100)]string RuntimeVersion { get; }

            // Reference3
            [DispId(120)] bool SpecificVersion { getset; }
            [DispId(121)] string SubType { getset; }
            [DispId(122)] bool Isolated { getset; }
            [DispId(123)] string Aliases { getset; }
            [DispId(124)] uint RefType { get; }
            [DispId(125)] bool AutoReferenced { get; }
            [DispId(126)] bool Resolved { get; }

            // Reference4
            [DispId(127)] bool EmbedInteropTypes { getset; }
        }
                Project proj = _applicationObject.Solution.Projects.Item(1);
                VSProject vsProj = (VSProject)proj.Object;
                Reference4 firstRef = vsProj.References.Item(1) as Reference4;
                firstRef.EmbedInteropTypes = true;

    Sincerely,


    Ed Dore
    Wednesday, October 13, 2010 5:48 PM
  • Thanks! This works great, especially I can embed this code to mine supporting both VS2008 & 2010 in one single assembly.
    sorpor
    Tuesday, October 19, 2010 8:45 PM
  • Hi Ed,

    This solution doesn't work for me. The cast to Reference4 doesn't throws an exception. But when i am accessing one of the properties from the Reference4 interface it throws a System.AccessViolationException

    Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    StackTrace:
    at Reference4.set_EmbedInteropTypes(Boolean value)
    ...

    Any thoughts on this one?

    Thanks in advance,

    Martijn

     PS. I run on a 64bits OS.



    • Edited by M Burgers Thursday, May 19, 2011 7:11 PM
    Thursday, May 19, 2011 6:21 PM
  • I am little bit further with my issue. The problem is that I am running this code on a different thread. If I do this on the main it works fine. But I don't want that because otherwise my winform hangs.
            //reference
            var newVsReference = VsProject.References.Add(reference.Location);
    
            //reference3 type is vs2008 (vslangproj80)
            var newVsReference3 = newVsReference as Reference3;
            if (newVsReference3 != null)
            {
              newVsReference3.SpecificVersion = reference.SpecificVersion;
              newVsReference3.CopyLocal = reference.CopyLocal;       
            }
            
            //reference4 type is vs2010 - this is missing in vslangproj100
            var newVsReference4 = newVsReference as Reference4;
            if (newVsReference4 != null)
            {
              newVsReference4.EmbedInteropTypes = reference.EmbedInteropTypes;        
            }  
    
    The SpecificVersion and CopyLocal properties of the Reference3 interface can be changed without an exception even on a different thread. Only the set on the EmbedInteropTypes property throws an exception.
    Any ideas?

    Gr
    Martijn
    Thursday, May 19, 2011 7:11 PM
  • I finally got it working. The GUID 5021602E-2025-4299-88D2-0A92E8B41ADF on the interface is wrong. This is the GUID from the Reference3 interface.

    The correct one is F71B6036-80F1-4F08-BC59-B5D92865F629. This could be checked using the OLE/COM Object Viewer.

    For some reason the wrong GUID works on the main thread but not on a different worker thread.

    The correct interface should be:

    [Guid("F71B6036-80F1-4F08-BC59-B5D92865F629")]
      public interface Reference4
      {    
        // Reference    
        [DispId(1)] DTE DTE { get; }    
        [DispId(2)] References Collection { get; }    
        [DispId(3)] Project ContainingProject { get; }    
        [DispId(4)] void Remove();    
        [DispId(5)] string Name { get; }    
        [DispId(6)] prjReferenceType Type { get; }    
        [DispId(7)] string Identity { get; }    
        [DispId(8)] string Path { get; }    
        [DispId(9)] string Description { get; }    
        [DispId(10)] string Culture { get; }    
        [DispId(11)] int MajorVersion { get; }    
        [DispId(12)] int MinorVersion { get; }    
        [DispId(13)] int RevisionNumber { get; }    
        [DispId(14)] int BuildNumber { get; }    
        [DispId(15)] bool StrongName { get; }    
        [DispId(16)] Project SourceProject { get; }    
        [DispId(17)] bool CopyLocal { get; set; }    
        [DispId(18), TypeLibFunc(1088)] dynamic get_Extender(string ExtenderName);    
        [DispId(19)] dynamic ExtenderNames { get; }    
        [DispId(20)] string ExtenderCATID { get; }    
        [DispId(21)] string PublicKeyToken { get; }    
        [DispId(22)] string Version { get; }     
        // Reference2    
        [DispId(100)]string RuntimeVersion { get; }     
        // Reference3    
        [DispId(120)] bool SpecificVersion { get; set; }    
        [DispId(121)] string SubType { get; set; }    
        [DispId(122)] bool Isolated { get; set; }    
        [DispId(123)] string Aliases { get; set; }    
        [DispId(124)] uint RefType { get; }    
        [DispId(125)] bool AutoReferenced { get; }   
        [DispId(126)] bool Resolved { get; }    
        // Reference4    
        [DispId(127)] bool EmbedInteropTypes { get; set; }  
      }
    

    Saturday, May 21, 2011 3:29 PM
  • Most VS COM interfaces are STA and thus must be run on the creating thread (the UI thread).

    Ryan

    Saturday, May 21, 2011 4:08 PM