How to get a COM reference to an Internet Explorer instance embedded in another application
Asked Answered
Z

2

6

The Dynamics plugin for Outlook displays content via an Internet Explorer embedded window. I'm trying to find a way to get at the SHDocVw.InternetExplorer COM object for that embedded window. Our application runs stand-alone (it's not an Outlook or IE add-in) and we are not at all in control of creation of the embedded IE window.

When I use:

Dim SWs As SHDocVw.ShellWindows
Set SWs = New SHDocVw.ShellWindows

the SWs collection does not contain a reference to the embedded browser in Outlook (though I do get references to regular browser windows).

Using Spy++, I see the following window hierarchy for the embedded Outlook window:

Window "xxxxxx" WindowsForms10.Window.8.app.0.5c39d4_r64_ad2
  - "" Shell Embedding
    - "" Shell DocObject View
      - "" Internet Explorer_Server

The last two windows in the hierarchy (Shell DocObject View and Internet Explorer_Server) are exactly the same as for the embedded viewer in a running Internet Explorer instance.

It seems like there must be some way to get a COM reference to these embedded browsers - any help or ideas would be greatly appreciated.

Zerla answered 21/6, 2012 at 21:21 Comment(0)
S
5

See KB 249232. You can get the IHTMLDocument2 pointer from the Internet Explorer_Server window using accessibility stuff. It ain't pretty, and it won't work if you're running in a different integrity level than the target process.

Depending on what you're doing, you may destabalize the target app, so be careful. And be mindful of the marshalling.

Shrewmouse answered 22/6, 2012 at 22:15 Comment(2)
You just made my day - that'll work smashingly. Thanks! I'll give this a whirl Monday and post back news of success.Zerla
Good luck. Nothing is ever as easy as it seems with this stuff. :)Shrewmouse
O
2

Here is how you can get HTMLDocument using Hwnd :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;
    using mshtml;

    namespace HookBrowser
    {
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        #region API CALLS

        [DllImport("user32.dll", EntryPoint = "GetClassNameA")]
        public static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);

        /*delegate to handle EnumChildWindows*/
        public delegate int EnumProc(IntPtr hWnd, ref IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern int EnumChildWindows(IntPtr hWndParent, EnumProc lpEnumFunc, ref  IntPtr lParam);
        [DllImport("user32.dll", EntryPoint = "RegisterWindowMessageA")]
        public static extern int RegisterWindowMessage(string lpString);
        [DllImport("user32.dll", EntryPoint = "SendMessageTimeoutA")]
        public static extern int SendMessageTimeout(IntPtr hwnd, int msg, int wParam, int lParam, int fuFlags, int uTimeout, out int lpdwResult);
        [DllImport("OLEACC.dll")]
        public static extern int ObjectFromLresult(int lResult, ref Guid riid, int wParam, ref IHTMLDocument2 ppvObject);
        public const int SMTO_ABORTIFHUNG = 0x2;
        public Guid IID_IHTMLDocument = new Guid("626FC520-A41E-11CF-A731-00A0C9082637");

        #endregion

        public IHTMLDocument2 document;

        private void button1_Click(object sender, EventArgs e)
        {
            document = documentFromDOM();
            /// check that we have hold of the IHTMLDocument2...
            if (!(bool)(document == null))
            {
                this.Text = document.url;
            }
        }

        private IHTMLDocument2 documentFromDOM()
        {
            Process[] processes = Process.GetProcessesByName("iexplore");
            if (processes.Length > 0)
            {
                IntPtr hWnd = processes[0].MainWindowHandle;
                int lngMsg = 0;
                int lRes;

                EnumProc proc = new EnumProc(EnumWindows);
                EnumChildWindows(hWnd, proc, ref hWnd);
                if (!hWnd.Equals(IntPtr.Zero))
                {
                    lngMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
                    if (lngMsg != 0)
                    {
                        SendMessageTimeout(hWnd, lngMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, out lRes);
                        if (!(bool)(lRes == 0))
                        {
                            int hr = ObjectFromLresult(lRes, ref IID_IHTMLDocument, 0, ref document);
                            if ((bool)(document == null))
                            {
                                MessageBox.Show("NoLDocument Found!", "Warning");
                            }
                        }
                    }
                }
            }
            return document;
        }

        private int EnumWindows(IntPtr hWnd, ref IntPtr lParam)
        {
            int retVal = 1;
            StringBuilder classname = new StringBuilder(128);
            GetClassName(hWnd, classname, classname.Capacity);
            /// check if the instance we have found is Internet Explorer_Server
            if ((bool)(string.Compare(classname.ToString(), "Internet Explorer_Server") == 0))
            {
                lParam = hWnd;
                retVal = 0;
            }
            return retVal;
        }
    }
}

Please refer to this link for more info :

http://www.xtremevbtalk.com/code-library/295336-internet-explorer-dom-using-objectfromlresult.html

Oversight answered 14/7, 2018 at 17:52 Comment(2)
It's a good idea to include the specific content from a link into your answer. Partly, it saves users time when evaluating your answer in their situation, but more importantly, it preserves the value of your answer if the link content is changed or deleted. See stackoverflow/help/how-to-answerHit
Added code snippet in the answer as suggested by @HitOversight

© 2022 - 2024 — McMap. All rights reserved.