ATL建立ActiveX控件(三)

示例代码http://download.csdn.net/source/1458175

控件在使用时会遇到很多的问题所以进行控件编程要有耐心,我把我遇到的问题简单说一下:

     一、控件的安全描述问题

但是我们在运行这个控件时是不是要弹出一个叫什么不安全交互的对话框呀,就是这个

这个很烦人呢,通常当我们把这个网页放在网站上运行时第一个对话框就不会弹了,但是第二个这样去不掉的,这主要是因为没有给控件加上安全描述,在MFCOCX中我们可以在注册时加上一些操作(OCX在这里我们不讲了,如有需要请给我留言吧!),但是这个ATL工程和OCX可就不一样了,我一开始也把它当OCX一样弄但费了好大劲,把我累的鼻子都找不到了也不行。后来我找到了一种非常好的方法。很简单,就两行代码,

第一步就是让控件类实现一个安全接口,继承一下就可以了。加入代码如下:

public IObjectSafetyImpl<CPlayerCtrl,INTERFACESAFE_FOR_UNTRUSTED_CALLER  | INTERFACESAFE_FOR_UNTRUSTED_DATA >

后面的两个参数的意义:

INTERFACESAFE_FOR_UNTRUSTED_CALLER - safe for scripting (安全描述)

     INTERFACESAFE_FOR_UNTRUSTED_DATA   - safe for initialization from data (安全初始化)

扫描二维码关注公众号,回复: 11815465 查看本文章

第二步加入安全初始化事件入口映射,代码如下:

COM_INTERFACE_ENTRY(IObjectSafety)

一切OK了,你再运行下下,是不是那破东东没有了呀。呵呵。

二、控件在IE中运行就崩的问题

         我们知现在好多的程序都使用了钩子,特别是像迅雷呀,还有什么江民杀毒呀都有,本来他们这些构子对我们也没有什么影响,可是不知怎的三下两下就钩到我们的控件里面去了,结果就把我们控件的魂都钩去了,崩了。。。

但是我只要让问题重现,就可以用代码来调试,原来是这样呀!我们的控件是用ATL来写的,为了让网页去调用,我们实现了IDispatch接口,但是这个接口对外公开的,所以任何一个人只要得到了就可去调用,如果这时有些接口我们没有进一步去实现,所以这时要是原来的代码不周密,那我们的控件生命期也就宣布Over 了。所以遇到这些情况也很好搞,你只要看看是哪个接口函数的问题,把这个接口再来完善的改一下就可以了。下面我是我遇到的一个迅雷钩子的解决办法

     //为了避免讯雷的钩子会使插件崩溃,重载IDispatchImpl接口的函数实现

     STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,    LCID lcid, DISPID* rgdispid)

     {

         if( rgszNames[0] == NULL )//加入一个判断,就可以防止崩溃了

              return S_OK;

         return IDispatchImpl<IPlayerCtrl, &IID_IPlayerCtrl, &LIBID_PlayerLib,1,0>::GetIDsOfNames( riid,  rgszNames,  cNames, lcid,  rgdispid);

     }

三、             静态全局生命周期的对象或变量不能使用

我们控件在使用时都要被其它的容器包含,那么控件的生命期就会由容器来决定,我们可以建立多个不同的控件实例。但是这时我们要注意如果我们在控件中使用全局静态对象,那这个静态对象对于所有的控件来说只有一个,对于外部容器来说也是只有一个,甚至都可以访问的到。所以多个控件同时运行时就会乱套喽,一会儿是这个控件来用,一会儿又是那一个来用,所以控件要么不能运行,要么就会崩了。

这种情况在IE下是很多见的,因为IE中通常都会有多个对象。那么我们应如何解决,最直接和简单的就是不要使用全局周期的静态变量。

如果你真的要用也有种办法,那就是给你的控件加一个引用计数,只要有一个控件运行就可以把计数加一个,少一个就减一。正好我们可能利用全局静态变量的特性,在控件类中加一个静态变量,这样构造函数中对其加一个,析构中对引用减一,这样如果一担控件检测到引用大于1,那控件就不要运行内核了,这样就可防止多个内核同时运行而崩溃。

要想多个内核同时运行而不崩,那你还是把静态对象换成NEW指针吧。

这个情况我们延伸一下,可想如果我们在控件中用同一个符号作为要进行操作的文件的名字,也会出现同样的问题。所以解决就要看你自己的取舍了。

 

四、             IE中控件运行时只具有较低的权限

为了系统的安全,WindowsIE的运行降的很低,因为大多数病毒都是通过网络传过来的,IE直接网络交互极有可能会把恶意脚本和可执行的东西搞到本地。所以控件IE中运行作为IE的一部分存在,那么控件的权限也就会很低。可是到了VISTA中安全级别提高了,就是普通的应用程序也会受到聘用制,要想运行就要得到管理员的认可。这时的IE的权限低了极点,控件也不能对硬盘进行操作,不能创建也不能改写硬盘上数据,更是不允许操作注册表。这一个我们完了,有很多的东西控件都不能进行完成了。一个字“完了”,呵呵

我们怎么办呢? :-< 其实也好办,只是麻烦了一点。

1.  如果我们想为控件写一个配置文件怎么办呀?

呵呵简单呀,VISTA中也没有完全给你限死,给你留了一点。那就是我们用户临时文件下面,我们可以去看看这个文件下有什么鸟玩意,是不是白的、黑的、花的、绿的。。。什么鸟也有呀!呵呵,就是因Windows允许任何程序都对其操作的原因,在这儿控件可以大显神威了,想创建文件夹也行,删除文件也行,随你了,想怎么样就怎么样。

这个地方怎么在程序中找到呀?简单呀。

theReturn = ::GetTempPath(MAX_PATH, lpBuffer);

lpBuffer里就是文件夹的路径了。

2.  如果我想操作注册表,我还想在系统目录下放个文件怎么办呀?

这个也有一个好的办法。你可写一个简单的程序,主要的是体积要小,这个程序里你可以做任何你想做的事情。那么这个程序怎么用呀,这个简单,你把这个程序和你想用的DLL和文件了一起放在你的CAB包里一起随控件下来,然后在控件中把这个程序启动起来,这样你想做注册可以,你想放在系统目录下的文件也可以用这个程序把它拷贝到目的地。O了。

还有一个问题就是你在控件中启动另一个程序时会遇到一个问题,启动时可能要弹出一个对话框来询问是否以管理员身分执行。点确定就可以。

  到此控件的东西也讲的差不多了,如果这些你都懂了,那么你可以说是会ATL建控件了。如果你还有其他问题给我留言就好了。

猜你喜欢

转载自blog.csdn.net/wanghaisheng/article/details/4323327