我们有一个现有的软件,它使用shellwidnows访问Internet Explorer页面并修改表单上的数据。但是,我们将其移植到Citrix无缝应用程序,并且shell窗口无法在那里工作。
我在互联网上环顾四周,找到了一种从现有IE窗口创建HtmlDocument的方法。
但是,我在尝试运行“SendMessageTimeout”时遇到问题。它运行时没有错误,但是当它应该是非零量时返回的结果为0。因此,我无法进入创建HTML文档的下一阶段。
导致问题的一行是: IntPtr result = SendMessageTimeout(htmlWindow,lMsg,IntPtr.Zero,IntPtr.Zero,SendMessageTimeoutFlags.SMTO_ABORTIFHUNG,1000,out lRes);
这是完整的代码。由于公司惯例,我使用VS 2008。我是C#的新手,所以一些约定和样式可能不正确。谢谢你的帮助。
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using mshtml;
using System.Diagnostics;
public delegate bool IECallBack(int hwnd, int lParam);
public delegate bool IEChildCallBack(int hWndParent, int lpEnumFunc, int lParam);
namespace GetIEWindows
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("Oleacc.Dll")]
public static extern int ObjectFromLresult(UIntPtr lResult, UUID _riid, int wParam, mshtml.HTMLDocument _ppvObject);
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
private static extern int FindWindowEx(int parentWindow, int childWindow, string _ClassName, string _WindowName);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.Dll")]
public static extern int EnumWindows(IECallBack x, long y);
[DllImport("user32.Dll")]
public static extern int EnumChildWindows(int parent, IECallBack x, long y);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
[DllImport("User32.Dll")]
public static extern void GetWindowText(IntPtr h, StringBuilder s, long nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("User32.Dll")]
public static extern void GetClassName(int h, StringBuilder s, int
nMaxCount);
[DllImport("User32.Dll")]
public static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out UIntPtr result);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
[Flags]
public enum SendMessageTimeoutFlags : uint
{
SMTO_NORMAL = 0x0,
SMTO_BLOCK = 0x1,
SMTO_ABORTIFHUNG = 0x2,
SMTO_NOTIMEOUTIFNOTHUNG = 0x8
}
public const int SMTO_ABORTIFHUNG = 0x2;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct UUID
{
public long Data1;
public int Data2;
public int Data3;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
}
public static mshtml.HTMLDocument GetHTMLContent(IntPtr htmlWindow)
{
HTMLDocument htmlDocument = new mshtml.HTMLDocument();
HTMLDocument thedoc = new mshtml.HTMLDocument();
IHTMLDocument htmlDoc = null;
Guid guid = new Guid("626FC520-A41E-11cf-A731-00A0C9082637");
int foundWindow = htmlWindow.ToInt32();
string htmlContent = "";
UUID IID_IHTMLDocument = new UUID();
UIntPtr lRes;
uint lMsg = 0;
int hr = 0;
if (foundWindow != 0)
{
// Register the message
lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
//lMsg = RegisterWindowMessage("WM_GETTEXT");
// Get the object
IntPtr result = SendMessageTimeout(htmlWindow, lMsg, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes);
if (result.ToInt32() != 0)
{
if (lRes != UIntPtr.Zero)
{
// 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, thedoc);
//htmlDoc = (mshtml.IHTMLDocument)ObjectFromLresult(, IID_IHTMLDocument, 0, htmlDoc);
}
catch (Exception e)
{
MessageBox.Show("Did not get IHTMLDocument: " + e.Message);
}
}
}
}
return thedoc;
}
public static void getHWnd()
{
string currentTitle;
string windowName = null;
string windowClass = "#32770";
HTMLDocument pageToBeEdited;
IntPtr hWnd = FindWindow(windowClass, windowName);
while (hWnd.ToInt32() != 0) {
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
currentTitle = sb.ToString();
if (currentTitle.Contains("Internet Explorer")) {
pageToBeEdited = GetHTMLContent(hWnd);
return;
}
hWnd = GetWindow(hWnd, GetWindow_Cmd.GW_HWNDNEXT);
}
return;
}
private void btnRun_Click(object sender, EventArgs e)
{
getHWnd();
}
}
}
答案 0 :(得分:6)
对于任何感兴趣的人,通过使用不同的getHWnd方式来解决问题:
public static IntPtr getHWnd(string title)
{
IntPtr hWnd = FindWindow(null, title);
BringWindowToTop(hWnd);
SetActiveWindow(hWnd);
SetForegroundWindow(hWnd);
Thread.Sleep(500);
foreach (Process process in Process.GetProcessesByName("IExplore"))
{
if (process.MainWindowTitle.ToLower().Contains(title.ToLower()))
{
hWnd = process.MainWindowHandle;
break;
}
}
EnumProc proc = new EnumProc(EnumWindows);
EnumChildWindows(hWnd, proc, ref hWnd);
return hWnd;
}
public HTMLDocument GetHTMLDocument(IntPtr hWnd)
{
HTMLDocument document = null;
int iMsg = 0;
int iRes = 0;
iMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
if (iMsg != 0)
{
SendMessageTimeout(hWnd, iMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, out iRes);
if (iRes != 0)
{
int hr = ObjectFromLresult(iRes, ref IID_IHTMLDocument, 0, ref document);
}
}
return document;
}
private static int EnumWindows(IntPtr hWnd, ref IntPtr lParam)
{
int iRet = 1;
StringBuilder classname = new StringBuilder(128);
GetClassName(hWnd, classname, classname.Capacity);
if ((bool)(string.Compare(classname.ToString(), "Internet Explorer_Server") == 0))
{
lParam = hWnd;
iRet = 0;
}
return iRet;
}
答案 1 :(得分:0)
以下是使用Hwnd获取HTMLDocument的方法:
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;
}
}
}
请参阅此链接以获取更多信息:
http://www.xtremevbtalk.com/code-library/295336-internet-explorer-dom-using-objectfromlresult.html