详解:IE无法打开二级页面

一、现象

有大量的网友遇到过“IE浏览器点击二级网页链接却无法打开”的现象。一般的解决方案是重新注册有关的dll文件。

重新注册以下DLL文件,在"开始"->"运行"对话框中逐条输入以下命令.
regsvr32 Shdocvw.dll
regsvr32 Actxprxy.dll
regsvr32 Shell32.dll
regsvr32 Oleaut32.dll
regsvr32 Mshtml.dll
regsvr32 Urlmon.dll
regsvr32 browscui.dll
regsvr32 msjava.dll

可是,这种现象是如何产生的呢?我们开发人员需要注意些什么呢?

 

二、原因

动态链接库dll在注册时会将com组件的类和接口写入注册表。比如Mshtml.dll中的IHTMLElement接口写入到注册表的HKEY_CLASSES_ROOT/Interface中。IE在打开二级网页的链接时,需要查询IHTMLElement接口的信息。如果这个接口丢失了,就会出现问题。因此,只需要regsvr32 Mshtml.dll 就可以解决问题了。同样,如果是其他接口丢失,就需要重新注册对应的dll文件。那么,在什么情况之下会出现接口丢失呢?

 

三、背景

我在vista下开发PIMShell,一切正常。后来在xp下测试时,发现当程序卸载后,IE无法打开二级页面。原来程序大量使用了mshtml.dll中的IHTMLXXX接口,在安装时,把IHTMLXXX接口注册到自己名下,从而导致在卸载时IHTMLXXX接口也被删除,于是IE找不到所需要的IHTMLXXX接口了。然而vista采用了Side By Side的程序部署方式,所以,即使我的程序卸载了,IHTMLXXX接口依然存在,因此不存在这个问题。

那么,我们开发人员需要怎样做才能避免这个问题呢?

 

四、解决方案

针对用户而言,解决方案就是重新注册dll文件。这里要讨论的是针对开发人员的解决方案。因为,程序正确了,用户也就不会有此困扰了。

方案一:

开发com组件时,接口方法的参数不要出现任何IHTMLXXX接口,用IDispatch接口代替。如:

HRESULT GetElement(BSTR bstrName,IDispatch** ppElement)

{

       CComPtr<IHTMLElement> pElement=this->__getElement(bstrName);

       return pElement->QueryInterface(IID_IDispatch,(void**)ppElement);

}

因为开发的com组件接口均没有使用IHTMLXXX接口,那么在注册时也就不会改变注册表中IHTMLXXX接口的行为了。

方案二:
如果要想在接口方法的参数中使用IHTMLXXX接口,那么就必须明确指示IHTMLXXX接口来自于Mshtml.dll,而不属于自己。这样,在注册时也不会改变IHTMLXXX接口的行为。如何做呢?

1、在IDL文件中导入mshtml的类型库,并定义接口

library PIMShellCore

{

   ...

   importlib("mshtml.tlb");
   ...
   HRESULT GetElement([in] BSTR bstrName,[out,retval] MSHTML.IHTMLElement** ppElement);

   ...
};

2、GetElement实现

HRESULT GetElement(BSTR bstrName,IHTMLElement** ppElement)

{

       CComPtr<IHTMLElement> pElement=this->__getElement(bstrName);

       *ppElement=pElement.Detach();

       return S_OK;

}

 

五、结论

虽然解决方案很简单,但为什么这个问题会大量存在呢?因为大多数的开发人员在开发ATL Com组件时采用属性化编程,从而不能使用类似MSHTML.IHTMLElement这样的语法,指示IHTMLElement接口来自mshtml.dll文件。幸运的是,visual studio 2008虽然支持属性化编程,但在新建ATL Com组件的向导中删除了“属性化”选项。所以,可以轻松的按照前面说的解决方案彻底解决“IE无法打开二级页面”的问题了。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值