Link to home
Start Free TrialLog in
Avatar of rabbitears
rabbitears

asked on

Help porting a few lines of c++ to C#

Basically, I need help porting a few lines of code from c++ to c#. Here's the basic idea.

1. Loop through every running instance of Internet Explorer on the current computer.
2. Get an IHTMLDocument2 from the HWND of each "Internet Explorer_Server" window.
3. Retrieve IHTMLDocument2.body.innerText.

Now, I've already done EVERYTHING except for number 3. And I'm really REALLY close to figuring it out, but I've spent SO much time trying to get it to work that I'm even closer to giving up... So I figured I'd just ask the pros here! :) It's really going to be a sweet piece of code if/when it can be made to work! In fact, I'm going to use it to make a VisualStudio.NET add-in that will shorten every ASP.NET build time by about 10 seconds! Well, technically it shortens the time BETWEEN builds, but when you're doing build after build after build... any time that can be saved is much appreciated.

As I said, all I'm really doing is porting c++ code to c#. Here are a few links that have helped me get this far. For anyone who is helping me out with this one, these links should DEFINITELY give you all the information you need to complete the code.

1. http://www.codeguru.com/internet/YahooChat_p2.html
This article shows EXACTLY how to retrive the text from an IHTMLDocument2 interface (#3 on the list above) in c++. This has the majority of the code we want to port.

2. http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q249232&
Here is a Microsoft article on "HOWTO: Get IHTMLDocument2 from a HWND". Again, this code is in c++

3. http://www.domaindlx.com/e_morcillo/scripts/tips/en/ie/iedom.asp
Here's where things get slightly interesting. This article is actually a port of the code in link 2 to VB! This was actually a pretty big help, as I don't think I could have made it this far without it! You'll see a few elements from the VB code that I ported to C# in my own code.

4. http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/document2/document2.asp
Here is the documentation for the IHTMLDocument2 Interface

5. http://msdn.microsoft.com/workshop/browser/mshtml/reference/reference.asp 
Here's a link to the MSHTML reference

And finally, here is my code!

The main line in question is:
hr = ObjectFromLresult(lRes, IID_IHTMLDocument, 0, iHTMLDocument2);

The problem seems to lie in how I prototype the ObjectFromLresult function (also included below) and the parameters that I pass to the function. Specifically, the second and third parameters. I feel as if I've tried every possible combination of IHTMLDocument, HTMLDocument, HTMLDocumentClass and IHtmlDocument2 that is possible. Sometimes the function will proceed, but the resultant object returned from the fourth parameter (HTMLDocument) is empty. The result is a NullReferenceException when you try to access thedoc.body.innerhtml.

The code below is a bit messy because I've been hacking on it all day, but I think that's the combination of parameters that should work best. The application is a VERY simple windows form application with a single listbox in it. The idea is to put the HTML content from each IE instance into a row in the listbox. I know that doesn't sound like a practical application, but that's really as far as I need help. The result, I assure you will be well worth it. Anyway, I've got everything working EXCEPT the part where you get the .innerText from the window and I've already discussed that situation.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Text;
using System.Runtime.InteropServices;


public delegate bool IECallBack(int hwnd, int lParam);

namespace Locaterr
{
     /// <summary>
     /// Summary description for Locaterr.
     /// </summary>
     ///


     public class Locaterr : System.Windows.Forms.Form
     {
         
          /// <summary>
          /// Required designer variable.
          /// </summary>
          private System.ComponentModel.Container components = null;
          static IntPtr listBoxHandle;// IntPtr is a class in System namespace
          static IntPtr windowHandle;
          static StringBuilder sb, sbc;
          private System.Windows.Forms.ListBox listBox1;

          public Locaterr()
          {
     
               
               //
               // Required for Windows Form Designer support
               //
               InitializeComponent();

               //
               // TODO: Add any constructor code after InitializeComponent call
               //
               listBoxHandle = listBox1.Handle;

               EnumWindows (new IECallBack(Locaterr.EnumWindowCallBack), (int)listBoxHandle) ;
          }

          private static bool EnumWindowCallBack(int hwnd, int lParam)
          {
               windowHandle = (IntPtr)hwnd;
               listBoxHandle = (IntPtr)lParam;
               int foundWindow;

               ListBox lb =(ListBox)ListBox.FromHandle(listBoxHandle);
               sb = new StringBuilder(1024);
               sbc = new StringBuilder(256);
               GetClassName(hwnd,sbc,sbc.Capacity);
               //GetWindowText((int)windowHandle, sb, sb.Capacity);

               
               //String xMsg  = sb+" "+sbc+" "+windowHandle;
               if( sbc.Length > 0 )
               {

                    if( sbc.ToString().Equals("IEFrame"))
                    {
                         foundWindow = FindWindowEx(hwnd, 0, "Shell DocObject View", "");                        
                         if (foundWindow != 0)
                         {
                             
                              foundWindow = FindWindowEx(foundWindow, 0, "Internet Explorer_Server", "");

                              string content = GetHTMLContent(foundWindow);

                              lb.Items.Add(content);


                         }
                         

                         
                    }

               }
               return true;
          }

          public static string GetHTMLContent(int htmlWindow)
          {
               
               mshtml.HTMLDocumentClass htmlDocumentClass = new mshtml.HTMLDocumentClass();
               mshtml.HTMLDocument htmlDocument = (mshtml.HTMLDocument)htmlDocumentClass;
               mshtml.IHTMLDocument2 iHTMLDocument2 = (mshtml.IHTMLDocument2)htmlDocumentClass;
               mshtml.IHTMLDocument iHTMLDocument = (mshtml.IHTMLDocument)htmlDocumentClass;

               Guid guid = new Guid("626FC520-A41E-11cf-A731-00A0C9082637");
               byte[] guidArray = guid.ToByteArray();

               int foundWindow = htmlWindow;
               string htmlContent = "";
                                   
               UUID IID_IHTMLDocument = new UUID();
               int lRes = 0;
               int lMsg = 0;
               int hr = 0;

               if (foundWindow != 0)
               {
                    // Register the message
                    lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
             
                    // Get the object
                    int result = SendMessageTimeout(htmlWindow, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, ref  lRes);
                    if (result != 0)
                    {
                         if (lRes > 0)
                         {
                              // Initialize the interface ID
                              IID_IHTMLDocument.Data1 = 0x626FC520;
                              IID_IHTMLDocument.Data2 = 0xA41E;
                              IID_IHTMLDocument.Data3 = 0x11CF;

                              IID_IHTMLDocument.Data4 = new byte[8];
                              IID_IHTMLDocument.Data4[0] = 0xA7;
                              IID_IHTMLDocument.Data4[1] = 0x31;
                              IID_IHTMLDocument.Data4[2] = 0x0;
                              IID_IHTMLDocument.Data4[3] = 0xA0;
                              IID_IHTMLDocument.Data4[4] = 0xC9;
                              IID_IHTMLDocument.Data4[5] = 0x8;
                              IID_IHTMLDocument.Data4[6] = 0x26;
                              IID_IHTMLDocument.Data4[7] = 0x37;
                                             
                             
                         
                              // Get the object from lRes
                             
                              try
                              {
                                   
                                   hr = ObjectFromLresult(lRes, IID_IHTMLDocument, 0, iHTMLDocument2);
                                   
                                                 
                                                 
                                                 
                              }
                              catch (Exception e)
                              {
                                   MessageBox.Show("Did not get IHTMLDocument: " + e.Message);
                              }

                              try
                              {
                                   mshtml.IHTMLDocument2 test1 = (mshtml.IHTMLDocument2)iHTMLDocument;
                                   mshtml.IHTMLDocument test2 = (mshtml.IHTMLDocument)iHTMLDocument;
                                   mshtml.HTMLDocument test3 = (mshtml.HTMLDocument)iHTMLDocument;
                                   

                                   string text = iHTMLDocument2.body.innerText;
                                   
                              }
                              catch (Exception e)
                              {
                                   MessageBox.Show("Could not get inner text: " + e.Message);
                              }

                         }
                         
                    }
                   
               }
               return htmlContent;

          }

          [ StructLayout( LayoutKind.Sequential ) ]
               public struct UUID
          {
               public long Data1;
               public int Data2;
               public int Data3;
               [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=8)]
               public byte[] Data4;
          }


          [DllImport("Oleacc.Dll")]
          public static extern int ObjectFromLresult (long lResult, [MarshalAs(UnmanagedType.Struct)] UUID _riid, int wParam, mshtml.IHTMLDocument2 _ppvObject);

          [DllImport("user32.dll")]
          private static extern int FindWindowEx(int parentWindow, int childWindow, string _ClassName, string _WindowName);

          [DllImport("user32.Dll")]
          public static extern int EnumWindows(IECallBack x, int y);

          [DllImport("user32.Dll")]
          public static extern int EnumChildWindows(int parent, IECallBack x, int y);

          [DllImport("User32.Dll")]
          public static extern void GetWindowText(int h, StringBuilder s, int nMaxCount);

          [DllImport("User32.Dll")]
          public static extern void GetClassName(int h, StringBuilder s, int nMaxCount);

          [DllImport("User32.Dll")]
          public static extern int RegisterWindowMessage(string lpString );

          [DllImport("User32.Dll")]
          public static extern int SendMessageTimeout(int hWnd, int msg, int wParam, int _lParam, int fuFlags, int uTimeout, ref int _lpdwResult);

          public const int SMTO_ABORTIFHUNG = 0x2;


          /// <summary>
          /// Clean up any resources being used.
          /// </summary>
          protected override void Dispose( bool disposing )
          {
               if( disposing )
               {
                    if(components != null)
                    {
                         components.Dispose();
                    }
               }
               base.Dispose( disposing );
          }

         

          #region Windows Form Designer generated code
          /// <summary>
          /// Required method for Designer support - do not modify
          /// the contents of this method with the code editor.
          /// </summary>
          private void InitializeComponent()
          {
               this.listBox1 = new System.Windows.Forms.ListBox();
               this.SuspendLayout();
               //
               // listBox1
               //
               this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
               this.listBox1.Name = "listBox1";
               this.listBox1.Size = new System.Drawing.Size(360, 277);
               this.listBox1.TabIndex = 0;
               //
               // Locaterr
               //
               this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
               this.ClientSize = new System.Drawing.Size(360, 285);
               this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                            this.listBox1});
               this.Name = "Locaterr";
               this.Text = "Locaterr";
               this.ResumeLayout(false);

          }
          #endregion
     }
}
ASKER CERTIFIED SOLUTION
Avatar of DanRollins
DanRollins
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
rabbitears,
Please add a comment. You must keep in communication if you want an Expert to continue working on your problem.
-- Dan
rabbitears,  Are you listening with those floppy things? -- Dan
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
Accept a comment by DanRollins
Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

TheAvenger
EE Cleanup Volunteer