监听IE访问的URL
前段时间由于项目中需要做一个监听IE访问的URL,具体做什么用在这里就不细讲了,呵呵!好了开始开始进入主题吧.以在网上的解决方案和自己的最终的解决方案做介绍:
按照习惯还是先Google一把,看看有没有好的解决办法,google 就是NB,的确找了一些解决方案,不过下面这个比较多:通过FindWindowEx using spy++ to find the type of window找到IE的地址栏的句柄,然后通过SendMessage(地址栏句柄, WM_GETTEXT, 1024, buffer);获取地址栏的URL。因为这个方案是网上找的代码所以就直接上代码了:
1 public static string GetURL(IntPtr parent)
2 {
3 IntPtr child = FindWindowEx(parent, 0, "WorkerW", null);
4 child = FindWindowEx(child, 0, "ReBarWindow32", null);
5 child = FindWindowEx(child, 0, "ComboBoxEx32", null);
6 child = FindWindowEx(child, 0, "ComboBox", null);
7 child = FindWindowEx(child, 0, "Edit", null); //通过SPY++获得地址栏的层次结构,然后一层一层获得
8 StringBuilder buffer = new StringBuilder(1024);
9
10 //child表示要操作窗体的句柄号
11 //WM_GETTEXT表示一个消息,怎么样来驱动窗体
12 //1024表示要获得text的大小
13 //buffer表示获得text的值存放在内存缓存中
14 int num = SendMessage(child, WM_GETTEXT, 1024, buffer);
15
16 string URL = buffer.ToString().Trim().Trim('\\').Trim('/').ToLower();
17 return URL;
18 }
2 {
3 IntPtr child = FindWindowEx(parent, 0, "WorkerW", null);
4 child = FindWindowEx(child, 0, "ReBarWindow32", null);
5 child = FindWindowEx(child, 0, "ComboBoxEx32", null);
6 child = FindWindowEx(child, 0, "ComboBox", null);
7 child = FindWindowEx(child, 0, "Edit", null); //通过SPY++获得地址栏的层次结构,然后一层一层获得
8 StringBuilder buffer = new StringBuilder(1024);
9
10 //child表示要操作窗体的句柄号
11 //WM_GETTEXT表示一个消息,怎么样来驱动窗体
12 //1024表示要获得text的大小
13 //buffer表示获得text的值存放在内存缓存中
14 int num = SendMessage(child, WM_GETTEXT, 1024, buffer);
15
16 string URL = buffer.ToString().Trim().Trim('\\').Trim('/').ToLower();
17 return URL;
18 }
1 public static void SetUrl(IntPtr hIEWnd, bool isWinRun)
2 {
3 //System.Threading.Thread.Sleep(200);
4 //using spy++ to find the type of window
5 IntPtr hCtrlWnd = FindWindowEx(hIEWnd, 0, "WorkerW", null);
6
7 hCtrlWnd = FindWindowEx(hCtrlWnd, 0, "ReBarWindow32", null);
8 hCtrlWnd = FindWindowEx(hCtrlWnd, 0, "ComboBoxEx32", null);
9
10 hCtrlWnd = FindWindowEx(hCtrlWnd, 0, "ComboBox", null);
11 IntPtr hUrlWnd = FindWindowEx(hCtrlWnd, 0, "Edit", null);
12
13 StringBuilder strUrl = new StringBuilder("http://www.baidu.com");
14
15 //set IE url
16 SendMessage(hUrlWnd, WM_SETTEXT, 0, strUrl);
17 //refresh IE
18 SendMessage(hUrlWnd, WM_KEYDOWN, VK_RETURN, null);
19 //activate the window
20 SendMessage(hIEWnd, WM_ACTIVATE, 0, null);
21
22 }
2 {
3 //System.Threading.Thread.Sleep(200);
4 //using spy++ to find the type of window
5 IntPtr hCtrlWnd = FindWindowEx(hIEWnd, 0, "WorkerW", null);
6
7 hCtrlWnd = FindWindowEx(hCtrlWnd, 0, "ReBarWindow32", null);
8 hCtrlWnd = FindWindowEx(hCtrlWnd, 0, "ComboBoxEx32", null);
9
10 hCtrlWnd = FindWindowEx(hCtrlWnd, 0, "ComboBox", null);
11 IntPtr hUrlWnd = FindWindowEx(hCtrlWnd, 0, "Edit", null);
12
13 StringBuilder strUrl = new StringBuilder("http://www.baidu.com");
14
15 //set IE url
16 SendMessage(hUrlWnd, WM_SETTEXT, 0, strUrl);
17 //refresh IE
18 SendMessage(hUrlWnd, WM_KEYDOWN, VK_RETURN, null);
19 //activate the window
20 SendMessage(hIEWnd, WM_ACTIVATE, 0, null);
21
22 }
当然我们还要引用API:
1 [DllImport("User32.dll")] //User32.dll是Windows操作系统的核心动态库之一
2 static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
3 [DllImport("User32.dll")]
4 static extern IntPtr FindWindowEx(IntPtr hwndParent, int hwndChildAfter, string lpszClass, string lpszWindow);
5 [DllImport("User32.dll")]
6 static extern IntPtr GetWindowText(IntPtr hwnd, StringBuilder buf, int nMaxCount);
7 [DllImport("User32.dll")]
8 static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, StringBuilder lParam);
2 static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
3 [DllImport("User32.dll")]
4 static extern IntPtr FindWindowEx(IntPtr hwndParent, int hwndChildAfter, string lpszClass, string lpszWindow);
5 [DllImport("User32.dll")]
6 static extern IntPtr GetWindowText(IntPtr hwnd, StringBuilder buf, int nMaxCount);
7 [DllImport("User32.dll")]
8 static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, StringBuilder lParam);
于是就想到了用WMI中的WqlEventQuery来获取启动进程的ID 然后通过Process proc = Process.GetProcessById(pid);来获取进程的句柄然后再调用上面的函数来获取或者设定IE的URL。经过测试IE6下面可以运行,但是偶尔还是会出现获取不了地址栏URL的情况,获取的是什么Autocompleteproxy 什么的,什么东东,不是很稳定,这当然不行,并且这种方式在IE7下测试好像通不过,所以这个方案就到此夭折了。
最后采用的方案是:
ShellWindows 来实现这个功能,好了不多说了 直接上代码吧;
1 /**
2 * By Fs.song
3 * 修改请注明自己的名字及修改原因
4 * 以上信息请保留 谢谢
5 * */
6 using System;
7 using System.Collections.Generic;
8 using System.Text;
9 using System.Runtime.InteropServices;
10 using System.Threading;
11 using SHDocVw;
12 using System.IO;
13 using Microsoft.Win32;
14
15 namespace Fs.Song.code
16 {
17 public class IEStartPageOperator
18 {
19 private static IEStartPageOperator _instance = new IEStartPageOperator();
20 ShellWindows shellWindows;
21 private IEStartPageOperator()
22 {
23
24 }
25 public static IEStartPageOperator getInstance()
26 {
27 return _instance;
28 }
29 public void Start()
30 {
31 if (shellWindows == null)
32 {
33 shellWindows = new ShellWindows();
34 }
35 shellWindows.WindowRegistered += new DShellWindowsEvents_WindowRegisteredEventHandler(Register);
36 }
37 public void Stop()
38 {
39 shellWindows.WindowRegistered -= new DShellWindowsEvents_WindowRegisteredEventHandler(Register);
40 }
41 private void Register(int ICookie)
42 {
43 for (int i = shellWindows.Count - 1; i >= 0; i--)
44 {
45 InternetExplorer ie = shellWindows.Item(i) as InternetExplorer;
46 string filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
47 if (filename.Equals("iexplore"))
48 {
49 string strUrl = ie.LocationURL;//IE8 url为打开IE的实际路径 但是IE7这里是""只能在
50 ie.NavigateComplete2 += new DWebBrowserEvents2_NavigateComplete2EventHandler(BeforeNavigate); break;//因为最后一个一定是最新创建的(自己测试后的结论)注意这里我是从后面遍历的找到最新创建的就退出循环 保证只处理新创建的IE 保证每个实例在这里只遍历一次
51 }
52 }
53 }
54 private void BeforeNavigate(object pDisp, ref object URL)
55 {
56 string strUrl = URL;
57 //做你自己想做的事情
58 }
59 }
60 }
当然上面的代码只是一个简单的框架想要什么功能自己想着往里面加吧,做软件的别什么都想让别人都替你做好了,那样也就失去了写代码的乐趣了,有了一个大体的框架去按照的自己的想去尽情的发挥,你会发现其实你可以做的更好。本人愚见写代码最快乐的不是看到结果的时候而是自己得到一个灵感的时候。当你用自己的思维方式去写代码的时候你会觉得很有成就感。最后说一句:”千万别让写代码成为一种体力劳动!”
3 * 修改请注明自己的名字及修改原因
4 * 以上信息请保留 谢谢
5 * */
6 using System;
7 using System.Collections.Generic;
8 using System.Text;
9 using System.Runtime.InteropServices;
10 using System.Threading;
11 using SHDocVw;
12 using System.IO;
13 using Microsoft.Win32;
14
15 namespace Fs.Song.code
16 {
17 public class IEStartPageOperator
18 {
19 private static IEStartPageOperator _instance = new IEStartPageOperator();
20 ShellWindows shellWindows;
21 private IEStartPageOperator()
22 {
23
24 }
25 public static IEStartPageOperator getInstance()
26 {
27 return _instance;
28 }
29 public void Start()
30 {
31 if (shellWindows == null)
32 {
33 shellWindows = new ShellWindows();
34 }
35 shellWindows.WindowRegistered += new DShellWindowsEvents_WindowRegisteredEventHandler(Register);
36 }
37 public void Stop()
38 {
39 shellWindows.WindowRegistered -= new DShellWindowsEvents_WindowRegisteredEventHandler(Register);
40 }
41 private void Register(int ICookie)
42 {
43 for (int i = shellWindows.Count - 1; i >= 0; i--)
44 {
45 InternetExplorer ie = shellWindows.Item(i) as InternetExplorer;
46 string filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
47 if (filename.Equals("iexplore"))
48 {
49 string strUrl = ie.LocationURL;//IE8 url为打开IE的实际路径 但是IE7这里是""只能在
50 ie.NavigateComplete2 += new DWebBrowserEvents2_NavigateComplete2EventHandler(BeforeNavigate); break;//因为最后一个一定是最新创建的(自己测试后的结论)注意这里我是从后面遍历的找到最新创建的就退出循环 保证只处理新创建的IE 保证每个实例在这里只遍历一次
51 }
52 }
53 }
54 private void BeforeNavigate(object pDisp, ref object URL)
55 {
56 string strUrl = URL;
57 //做你自己想做的事情
58 }
59 }
60 }