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

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

贺星河 2005-11-7

          

【文章目的】

.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

 

【小结】

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

 

全文完

 

附件:源程序FlashUrlTest.rar,我的.net2.0版本为 2.0.50727,请注意

posted on 2005-11-15 21:59  团团ta爸  阅读(4667)  评论(7编辑  收藏

导航