HOWTO: Getting IDesignerHost and IHTMLDocument of WebForms from a Visual Studio .NET add-in

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio .NET 2002
Date: April 2005   Microsoft Visual Studio .NET 2003
      Microsoft Visual Studio 2005

This article describes how to get the IDesignerHost and IHTMLDocument interfaces of WebForms and HTML pages from a Visual Studio .NET IDE add-in.

More Information

The EnvDTE.Window.Object returns an object that can be cast to different types, depending on the kind of the window. For Windows forms, it can be cast to a System.ComponentModel.Design.IDesignerHost, in order to get access to the controls of the form. For Web forms and HTML pages, it is not so easy. This article shows the code to do this.

Note: to get the IDesignerHost interface of a Web form you need the definition for the IServiceProvider interface. You can get this interface as explained in the article HOWTO: Get a Visual Studio service from an add-in.

The sample code (VB.NET) is shown below. When loaded, this add-in retrieves the IDesignerHost and IHTMLDocument2 interfaces of the active window, assuming that it is a Web form. You need to add references to Microsoft.VisualStudio.OLE.Interop.dll and Microsoft.MSHtml. To get more information about MSHTML, visit:


Public Sub OnConnection(ByVal application As Object, _
   ByVal connectMode As ext_ConnectMode, ByVal addInInst As Object, _
   ByRef custom As Array) Implements IDTExtensibility2.OnConnection

   ' Imports System.ComponentModel.Design
   ' Imports System.Windows.Forms

   Dim objIDesignerHost As IDesignerHost
   Dim objHTMLWindow As EnvDTE.HTMLWindow
   Dim objIServiceProvider As Microsoft.VisualStudio.OLE.Interop.IServiceProvider
   Dim objObject As Object
   Dim objIntPtr As IntPtr
   Dim objSIDGuid As Guid
   Dim objIIDGuid As Guid
   Dim hr As Integer
   Dim objWindow As Window
   Dim objIHTMLDocument2 As mshtml.IHTMLDocument2
   Dim objComponentContainer As Object


      Select Case connectMode

         Case ext_ConnectMode.ext_cm_AfterStartup, ext_ConnectMode.ext_cm_Startup

            applicationObject = CType(application, EnvDTE.DTE)
            addInInstance = CType(addInInst, EnvDTE.AddIn)

            objWindow = applicationObject.ActiveDocument.ActiveWindow

            If Not (objWindow Is Nothing) Then

               If Not (objWindow.Object Is Nothing) Then

                  If TypeOf objWindow.Object Is IDesignerHost Then   ' Windows form

                     objIDesignerHost = CType(objWindow.Object, IDesignerHost)

                  ElseIf TypeOf objWindow.Object Is EnvDTE.HTMLWindow Then  ' Web form

                     ' Get the HTML window
                     objHTMLWindow = DirectCast(objWindow.Object, EnvDTE.HTMLWindow)

                     ' Get the current tab
                     objObject = objHTMLWindow.CurrentTabObject

                     ' Get the IHTMLDocument2 interface
                     objIHTMLDocument2 = DirectCast(objObject, mshtml.IHTMLDocument2)

                     MessageBox.Show("The body content is : " & objIHTMLDocument2.body.innerHTML)

                     ' Get the IDesignerHost
                     objIServiceProvider = DirectCast(objObject, _
                     objSIDGuid = New Guid("7494682a-37a0-11d2-a273-00c04f8ef4ff")
                     objIIDGuid = objSIDGuid
                     hr = objIServiceProvider.QueryService(objSIDGuid, objIIDGuid, objIntPtr)

                     If hr <> 0 Then


                     ElseIf Not objIntPtr.Equals(IntPtr.Zero) Then

                           objObject = _

                           If TypeOf objObject Is IDesignerHost Then ' Visual Studio NET 2002/2003

                              objIDesignerHost = DirectCast(objObject, IDesignerHost)


                              ' Visual Studio 2005 returns a VSDesignSurface object (in the 
                              ' Microsoft.VisualStudio.Design.dll assembly of the GAC)
                              ' whose ComponentContainer property actually returns the IDesignerHost 

                              objComponentContainer = objObject.GetType.InvokeMember( _
                                 "ComponentContainer", _
                                 Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public _
                                 Or Reflection.BindingFlags.GetProperty, Nothing, objObject, Nothing)

                              If TypeOf objComponentContainer Is IDesignerHost Then
                                 objIDesignerHost = DirectCast(objComponentContainer, IDesignerHost)
                              End If

                           End If

                        End Try

                        MessageBox.Show("The site name is " & _

                     End If

                  End If

               End If

            End If

      End Select

   Catch objException As Exception
   End Try

End Sub

Go to the 'Visual Studio Extensibility (VSX)' web site for more articles like this (Articles section)