conan

导航

使用Hook(钩子)阻止Flash启动浏览器打开URL

          

【文章目的】

.net程序中嵌入flash文件,为了防止有人通过flash右键菜单中的“关于Macromedia”打开ie访问internet,或者flash中通过GetURL()方法打开浏览器直接访问internet

 

【解决方案】

使用Hook技术,截获flash在启动外部浏览器访问internet时向系统发送的消息,然后用线程将外部浏览器Kill

 

【编程手记】

开发工具:VS2005 Beta2,Flash版本为flash 8

为了达到禁止Flash打开浏览器的目的,从HookHook不知道?天极里面资料很多的)入手,截获到Flash的相关事件信息,提前启动一个专杀浏览器的线程,使得Flash打开浏览器的瞬间关闭。我们先要找到Flash在播放电子杂志时候的一些相关数据,比如系统消息,发送给外部的消息结构为:

    [StructLayout(LayoutKind.Sequential)]

    
public struct CWPSTRUCT

    
{

        
public IntPtr lparam;

        
public IntPtr wparam;

        
public int message;

        
public IntPtr hwnd;

    }






//在C#中使用钩子

public delegate int HookProc(int code, IntPtr wparam, ref CWPSTRUCT cwp);

        
public static int WH_CALLWNDPROC = 0x004;



        
//安装钩子的函数

        [DllImport(
"user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall)]

        
public static extern IntPtr SetWindowsHookEx(int type, HookProc hook, IntPtr instance, int threadID);



        
//调用下一个钩子的函数

        [DllImport(
"user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        
public static extern int CallNextHookEx(IntPtr hookHandle, int code, IntPtr wparam, ref CWPSTRUCT cwp);



        
//卸载钩子

        [DllImport(
"User32.dll", CharSet = CharSet.Auto)]

        
public static extern bool UnhookWindowsHookEx(IntPtr hookHandle);



        
//获取窗体线程ID

        [DllImport(
"User32.dll", CharSet = CharSet.Auto)]

        
public static extern int GetWindowThreadProcessId(IntPtr hwnd, int ID);



        
private HookProc hookProc;

        
private IntPtr hookHandle = IntPtr.Zero;

    

这是打开Flash中一个含链接的事件时候截获的系统消息:

 

cwp.message =528 && cwp.wparam=513                                   //鼠标事件消息,在Flash上点击左右键盘都会发生

cwp.message =33cwp.lparam =33619969                                   

cwp.message =33cwp.lparam =33619969cwp.wparam=658836cwp.hwnd=724410

cwp.message =33cwp.lparam =33619969cwp.wparam=658836cwp.hwnd=658836

cwp.message =32cwp.lparam =33619969cwp.wparam=724410cwp.hwnd=724410

cwp.message =8cwp.lparam =0cwp.wparam=724410cwp.hwnd=527784

cwp.message =8cwp.lparam =0cwp.wparam=724410cwp.hwnd=527784

cwp.message =647cwp.lparam =527784cwp.wparam=24cwp.hwnd=658866       //当前窗口的得到或失去焦点消息

cwp.message =641cwp.lparam =-1073741809cwp.wparam=0cwp.hwnd=527784

cwp.message =641cwp.lparam =-1073741809cwp.wparam=0cwp.hwnd=658866

cwp.message =641cwp.lparam =-1073741809cwp.wparam=0cwp.hwnd=724374

cwp.message =647cwp.lparam =724410cwp.wparam=23cwp.hwnd=658866       //当前窗口得到或失去焦点信息

cwp.message =641cwp.lparam =-1073741809cwp.wparam=1cwp.hwnd=724410

cwp.message =641cwp.lparam =-1073741809cwp.wparam=1cwp.hwnd=658866

cwp.message =641cwp.lparam =-1073741809cwp.wparam=1cwp.hwnd=724374

cwp.message =992cwp.lparam =-1070940117cwp.wparam=855452cwp.hwnd=855452  //通知外部浏览器打开URL消息

cwp.message =992cwp.lparam =-1070940117cwp.wparam=855452cwp.hwnd=724374

cwp.message =992cwp.lparam =-1070940117cwp.wparam=855452cwp.hwnd=658866

cwp.message =992cwp.lparam =-1070940117cwp.wparam=855452cwp.hwnd=658836

cwp.message =996cwp.lparam =-1070940117cwp.wparam=462274cwp.hwnd=855452

 

从以上消息队列中可以找到Flash中相关事件的消息 message 的内容,查阅API的相关资料,经过测试可以得知,message=992 是想要截获的消息,截获到这个消息后,可以使用threadkill IEprocess(有人可能说这里可以直接将截获到的消息丢掉,实际上这是行不通的,有些钩子只能查看消息,不能修改消息,也不能通过返回非0值阻止消息继续传递。很不幸,我们用到的WH_CALLWNDPROC就是其中之一。MSDN里说得很清楚:After the hook procedure returns control to the system, the message is passed to the window procedure. 不过WH_GETMESSAGE钩子可以修改消息,大家可以试试看)

       #region 阻止Flash打开URL

        
private Thread killThread;

        
protected override void WndProc(ref Message m)

        {

            
base.WndProc(ref m);



            
if (m.Msg == 992)

            {

                
if (killThread != null)

                {

                    killThread.Abort();

                }



                killThread 
= new System.Threading.Thread(new System.Threading.ThreadStart(KillIE));

                killThread.IsBackground 
= true;

                killThread.Start();

            }

        }



        
private void KillIE()

        {

            
bool isKilled = false;

            
while (!isKilled)

            {

                System.Threading.Thread.Sleep(
10);

               
//这里当然也可以是关闭firefox/maxthon 等其他浏览器

                Process[] processes 
= System.Diagnostics.Process.GetProcessesByName("iexplore");

                
foreach (Process ps in processes)

                {

                    ps.Kill();

                    isKilled 
= true;

                    
break;

                }

            }

        }

        
#endregion



【小结】

本文只是在做项目的过程中碰到一个小的需求而进行的一个测验,解决方案有很多,目前为止这是我找到的一个性能比较高的方案,供大家参考,谢谢!

posted on 2005-11-18 10:39  Conan  阅读(874)  评论(0)    收藏  举报