最近小弟因为公司需要写了个BHO,但由于刚学遇见了一个不能解决的问题先贴代码
// EyeOnIE.cpp : Implementation of CEyeOnIE#include "stdafx.h"
#include "BhoPlugin.h"
#include "EyeOnIE.h"
#include "ExDispID.h"
#include <shlobj.h>
#include <string>
#include <comdef.h>
#include <sstream>#include <atlstr.h>
#include <sys/types.h>
#include <winsock.h>
#include <sys/types.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
#include <windows.h>
#pragma comment(lib, "wsock32.lib")
/////////////////////////////////////////////////////////////////////////////
// CEyeOnIE
STDMETHODIMP CEyeOnIE::SetSite(IUnknown *pUnkSite)
{
USES_CONVERSION;
if (pUnkSite)
{
mWebBrowser2 = pUnkSite;
if (mWebBrowser2)
{
return RegisterEventHandler(TRUE);
}
}
return E_FAIL;
}HRESULT CEyeOnIE::RegisterEventHandler(BOOL inAdvise)
{
CComPtr<IConnectionPoint> spCP;
// Receives the connection point for WebBrowser events
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> spCPC(mWebBrowser2);
HRESULT hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
if (FAILED(hr))
return hr; if (inAdvise)
{
// Pass the event handlers to the container
hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &mCookie);
}
else
{
spCP->Unadvise(mCookie);
}
return hr;
}
bool CheckNeedSave(char* p)
{
//判断是不是需要处理的name
//
std::string StringNeed="jsrxx.sfzmhm,jsrxx.xm,jsrxx.xb,jsrxx.csrq,jsrxx.zkcx,jsrxx.lxdh,jsrxx.lxzsxzqh,jsrxx.lxzsxxdz,jsrxx.djzsxzqh,jsrxx.djzsxxdz";
//StringNeed 是需要处理的name 集合
if (StringNeed.find(p)!=std::string::npos)
{
return true;
}
else
{
return false;
}
}//
STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams,
VARIANT * pvarResult,EXCEPINFO * pexcepinfo,
UINT * puArgErr){
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG; switch (dispidMember)
{
//
// The parameters for this DISPID are as follows:
// [0]: Cancel flag - VT_BYREF|VT_BOOL
// [1]: HTTP headers - VT_BYREF|VT_VARIANT
// [2]: Address of HTTP POST data - VT_BYREF|VT_VARIANT
// [3]: Target frame name - VT_BYREF|VT_VARIANT
// [4]: Option flags - VT_BYREF|VT_VARIANT
// [5]: URL to navigate to - VT_BYREF|VT_VARIANT
// [6]: An object that evaluates to the top-level or frame
// WebBrowser object corresponding to the event.
//
case DISPID_BEFORENAVIGATE2:
{
LPOLESTR lpURL = NULL;
mWebBrowser2->get_LocationURL(&lpURL);
char * strurl;
if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
{
CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
varURL.ChangeType(VT_BSTR);
strurl = OLE2A(varURL.bstrVal);
}
MessageBox(0,strurl,"",0);
if (strstr(strurl, "xxxxxx.html"))
{
HRESULT hr;
IDispatch* pDoc;
mWebBrowser2->get_Document(&pDoc);
if(pDoc)
{
IHTMLDocument2* pHTMLDoc = NULL;
IDispatch* pDispatch=NULL;
pDoc->QueryInterface(IID_IHTMLDocument2, (void**)&pHTMLDoc);
pDoc->QueryInterface(IID_IDispatch, (void**)&pDispatch);
CComQIPtr< IHTMLElementCollection > pElementCollection;
CComPtr<IHTMLFramesCollection2> spFramesCollection2;
pHTMLDoc->get_frames(&spFramesCollection2); //取得框架frame的集合
long nFrameCount=0; //取得子框架个数
hr=spFramesCollection2->get_length(&nFrameCount);
CComPtr <IHTMLDocument2> spDoc2;
for(long i=0; i<nFrameCount; i++)
{
CComVariant vDispWin2; //取得子框架的自动化接口
hr = spFramesCollection2->item(&CComVariant(i), &vDispWin2);
if (FAILED(hr)) continue;
CComQIPtr<IHTMLWindow2>spWin2 = vDispWin2.pdispVal;
//CComQIPtr<IHTMLFrameElement, &IID_IHTMLFrameElement> pFrmElement=vDispWin2.pdispVal;
if (!spWin2) continue; //取得子框架的 IHTMLWindow2 接口
CComPtr <IHTMLLocation> spLoc;
spWin2->get_location(&spLoc);//获取frame的页面地址
BSTR bHref;
spLoc->get_href(&bHref);//获取链接地址
CString strHref=bHref;
MessageBox(0,strHref,"",0);
//MessageBox(0,"!!!!","",0);
if(strHref=="xxxxxx.html")
{
//效能提升门户中间框架leftFrame的页面地址
spWin2->get_document(&spDoc2); //取得子框架的 IHTMLDocument2 接口
hr=spDoc2->get_forms(&pElementCollection);
if ( FAILED( hr ) )
{
// ::AfxMessageBox("获取表单的集合 IHTMLElementCollection 错误");
//return;
}
long nFormCount=0; //取得表单数目
hr = pElementCollection->get_length( &nFormCount );
if ( FAILED( hr ) )
{
// AfxMessageBox("获取表单数目错误");
// return;
}
//nFormCount=50;
//MessageBox(0,nFormCount+"!@!!!","",0);
for(long i=0; i<nFormCount; i++)
{
IDispatch *pDisp = NULL; //取得第 i 项表单
hr = pElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
if ( FAILED( hr ) ) continue; CComQIPtr< IHTMLFormElement > spFormElement = pDisp;
pDisp->Release(); long nElemCount=0; //取得表单中 域 的数目
hr = spFormElement->get_length( &nElemCount );
if ( FAILED( hr ) ) continue;
nElemCount=10;
for(long j=0; j<nElemCount; j++)
{
CComDispatchDriver spInputElement; //取得第 j 项表单域
hr = spFormElement->item( CComVariant( j ), CComVariant(), &spInputElement );
if ( FAILED( hr ) ) continue; CComVariant vName,vVal,vType; //取得表单域的 名,值,类型
hr = spInputElement.GetPropertyByName( L"name", &vName );
if( FAILED( hr ) )
continue;
hr = spInputElement.GetPropertyByName( L"value", &vVal );
if( FAILED( hr ) )
continue;
hr = spInputElement.GetPropertyByName( L"type", &vType );
if( FAILED( hr ) )
continue; //hr = spInputElement.GetPropertyByName( L"ID", &vType ); //spInputElement.getprop LPCTSTR lpName = vName.bstrVal?
OLE2CT( vName.bstrVal ) : ("NULL"); //未知域名
LPCTSTR lpVal = vVal.bstrVal?
OLE2CT( vVal.bstrVal ) : ("NULL"); //空值,未输入
LPCTSTR lpType = vType.bstrVal?
OLE2CT( vType.bstrVal ) : ("NULL"); //未知类型 // CString val;
// val.Format("type:[%s] -- name:%s -- value:%s",lpType,lpName,lpVal);
std::stringstream ss;
ss<<"type:"<<lpType<<"name:"<<lpName<<"val:"<<lpVal;
//如果是要处理的字段 保存到数据库
MessageBox(0,ss.str().c_str(),"",0);
if (CheckNeedSave((char *)lpName)) //判断是不是要处理的字段
{
//如果是要处理的字段 保存到数据库
MessageBox(0,ss.str().c_str(),"",0);
int sockfd;
int len;
struct sockaddr_in address;
int result;
char *strings="GET /BHOUrl/servlet/BhoServlet HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: Close\r\n\r\n";
char ch;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(8080);
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
send(sockfd, strings, strlen(strings), 0);
}
}
//想提交这个表单吗?删除下面语句的注释吧
//pForm->submit();
pDispatch->Release();
pHTMLDoc->Release();
pDoc->Release();
}
break;
}
}
}
}
///disp->QueryInterface();
}
break;
case DISPID_NAVIGATECOMPLETE2:
break;
case DISPID_DOCUMENTCOMPLETE: break;
case DISPID_DOWNLOADBEGIN:
break;
case DISPID_DOWNLOADCOMPLETE:
break;
case DISPID_NEWWINDOW2:
break;
case DISPID_QUIT:
RegisterEventHandler(FALSE);
break;
default:
break;
}
return S_OK;
}在本地测试很多web页面都行,但是唯独一个项目页面不行请教原因。
// EyeOnIE.cpp : Implementation of CEyeOnIE#include "stdafx.h"
#include "BhoPlugin.h"
#include "EyeOnIE.h"
#include "ExDispID.h"
#include <shlobj.h>
#include <string>
#include <comdef.h>
#include <sstream>#include <atlstr.h>
#include <sys/types.h>
#include <winsock.h>
#include <sys/types.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
#include <windows.h>
#pragma comment(lib, "wsock32.lib")
/////////////////////////////////////////////////////////////////////////////
// CEyeOnIE
STDMETHODIMP CEyeOnIE::SetSite(IUnknown *pUnkSite)
{
USES_CONVERSION;
if (pUnkSite)
{
mWebBrowser2 = pUnkSite;
if (mWebBrowser2)
{
return RegisterEventHandler(TRUE);
}
}
return E_FAIL;
}HRESULT CEyeOnIE::RegisterEventHandler(BOOL inAdvise)
{
CComPtr<IConnectionPoint> spCP;
// Receives the connection point for WebBrowser events
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> spCPC(mWebBrowser2);
HRESULT hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
if (FAILED(hr))
return hr; if (inAdvise)
{
// Pass the event handlers to the container
hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &mCookie);
}
else
{
spCP->Unadvise(mCookie);
}
return hr;
}
bool CheckNeedSave(char* p)
{
//判断是不是需要处理的name
//
std::string StringNeed="jsrxx.sfzmhm,jsrxx.xm,jsrxx.xb,jsrxx.csrq,jsrxx.zkcx,jsrxx.lxdh,jsrxx.lxzsxzqh,jsrxx.lxzsxxdz,jsrxx.djzsxzqh,jsrxx.djzsxxdz";
//StringNeed 是需要处理的name 集合
if (StringNeed.find(p)!=std::string::npos)
{
return true;
}
else
{
return false;
}
}//
STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams,
VARIANT * pvarResult,EXCEPINFO * pexcepinfo,
UINT * puArgErr){
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG; switch (dispidMember)
{
//
// The parameters for this DISPID are as follows:
// [0]: Cancel flag - VT_BYREF|VT_BOOL
// [1]: HTTP headers - VT_BYREF|VT_VARIANT
// [2]: Address of HTTP POST data - VT_BYREF|VT_VARIANT
// [3]: Target frame name - VT_BYREF|VT_VARIANT
// [4]: Option flags - VT_BYREF|VT_VARIANT
// [5]: URL to navigate to - VT_BYREF|VT_VARIANT
// [6]: An object that evaluates to the top-level or frame
// WebBrowser object corresponding to the event.
//
case DISPID_BEFORENAVIGATE2:
{
LPOLESTR lpURL = NULL;
mWebBrowser2->get_LocationURL(&lpURL);
char * strurl;
if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
{
CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
varURL.ChangeType(VT_BSTR);
strurl = OLE2A(varURL.bstrVal);
}
MessageBox(0,strurl,"",0);
if (strstr(strurl, "xxxxxx.html"))
{
HRESULT hr;
IDispatch* pDoc;
mWebBrowser2->get_Document(&pDoc);
if(pDoc)
{
IHTMLDocument2* pHTMLDoc = NULL;
IDispatch* pDispatch=NULL;
pDoc->QueryInterface(IID_IHTMLDocument2, (void**)&pHTMLDoc);
pDoc->QueryInterface(IID_IDispatch, (void**)&pDispatch);
CComQIPtr< IHTMLElementCollection > pElementCollection;
CComPtr<IHTMLFramesCollection2> spFramesCollection2;
pHTMLDoc->get_frames(&spFramesCollection2); //取得框架frame的集合
long nFrameCount=0; //取得子框架个数
hr=spFramesCollection2->get_length(&nFrameCount);
CComPtr <IHTMLDocument2> spDoc2;
for(long i=0; i<nFrameCount; i++)
{
CComVariant vDispWin2; //取得子框架的自动化接口
hr = spFramesCollection2->item(&CComVariant(i), &vDispWin2);
if (FAILED(hr)) continue;
CComQIPtr<IHTMLWindow2>spWin2 = vDispWin2.pdispVal;
//CComQIPtr<IHTMLFrameElement, &IID_IHTMLFrameElement> pFrmElement=vDispWin2.pdispVal;
if (!spWin2) continue; //取得子框架的 IHTMLWindow2 接口
CComPtr <IHTMLLocation> spLoc;
spWin2->get_location(&spLoc);//获取frame的页面地址
BSTR bHref;
spLoc->get_href(&bHref);//获取链接地址
CString strHref=bHref;
MessageBox(0,strHref,"",0);
//MessageBox(0,"!!!!","",0);
if(strHref=="xxxxxx.html")
{
//效能提升门户中间框架leftFrame的页面地址
spWin2->get_document(&spDoc2); //取得子框架的 IHTMLDocument2 接口
hr=spDoc2->get_forms(&pElementCollection);
if ( FAILED( hr ) )
{
// ::AfxMessageBox("获取表单的集合 IHTMLElementCollection 错误");
//return;
}
long nFormCount=0; //取得表单数目
hr = pElementCollection->get_length( &nFormCount );
if ( FAILED( hr ) )
{
// AfxMessageBox("获取表单数目错误");
// return;
}
//nFormCount=50;
//MessageBox(0,nFormCount+"!@!!!","",0);
for(long i=0; i<nFormCount; i++)
{
IDispatch *pDisp = NULL; //取得第 i 项表单
hr = pElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
if ( FAILED( hr ) ) continue; CComQIPtr< IHTMLFormElement > spFormElement = pDisp;
pDisp->Release(); long nElemCount=0; //取得表单中 域 的数目
hr = spFormElement->get_length( &nElemCount );
if ( FAILED( hr ) ) continue;
nElemCount=10;
for(long j=0; j<nElemCount; j++)
{
CComDispatchDriver spInputElement; //取得第 j 项表单域
hr = spFormElement->item( CComVariant( j ), CComVariant(), &spInputElement );
if ( FAILED( hr ) ) continue; CComVariant vName,vVal,vType; //取得表单域的 名,值,类型
hr = spInputElement.GetPropertyByName( L"name", &vName );
if( FAILED( hr ) )
continue;
hr = spInputElement.GetPropertyByName( L"value", &vVal );
if( FAILED( hr ) )
continue;
hr = spInputElement.GetPropertyByName( L"type", &vType );
if( FAILED( hr ) )
continue; //hr = spInputElement.GetPropertyByName( L"ID", &vType ); //spInputElement.getprop LPCTSTR lpName = vName.bstrVal?
OLE2CT( vName.bstrVal ) : ("NULL"); //未知域名
LPCTSTR lpVal = vVal.bstrVal?
OLE2CT( vVal.bstrVal ) : ("NULL"); //空值,未输入
LPCTSTR lpType = vType.bstrVal?
OLE2CT( vType.bstrVal ) : ("NULL"); //未知类型 // CString val;
// val.Format("type:[%s] -- name:%s -- value:%s",lpType,lpName,lpVal);
std::stringstream ss;
ss<<"type:"<<lpType<<"name:"<<lpName<<"val:"<<lpVal;
//如果是要处理的字段 保存到数据库
MessageBox(0,ss.str().c_str(),"",0);
if (CheckNeedSave((char *)lpName)) //判断是不是要处理的字段
{
//如果是要处理的字段 保存到数据库
MessageBox(0,ss.str().c_str(),"",0);
int sockfd;
int len;
struct sockaddr_in address;
int result;
char *strings="GET /BHOUrl/servlet/BhoServlet HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: Close\r\n\r\n";
char ch;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(8080);
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
send(sockfd, strings, strlen(strings), 0);
}
}
//想提交这个表单吗?删除下面语句的注释吧
//pForm->submit();
pDispatch->Release();
pHTMLDoc->Release();
pDoc->Release();
}
break;
}
}
}
}
///disp->QueryInterface();
}
break;
case DISPID_NAVIGATECOMPLETE2:
break;
case DISPID_DOCUMENTCOMPLETE: break;
case DISPID_DOWNLOADBEGIN:
break;
case DISPID_DOWNLOADCOMPLETE:
break;
case DISPID_NEWWINDOW2:
break;
case DISPID_QUIT:
RegisterEventHandler(FALSE);
break;
default:
break;
}
return S_OK;
}在本地测试很多web页面都行,但是唯独一个项目页面不行请教原因。
解决方案 »
- 如何实现软件的数据共享,求解决思路?
- 迅雷7的界面
- 大虾进
- 如何使datapicker控件显示为英文
- 如何成批获取行?大哥们请帮忙啊
- 【重分酬谢,寻儿启示: IDispatch(邪神) , 有知其下落者请与本人联系】
- ActiveX中创建的非模态对话框显示后,不能相应键盘操作?怎么解决?
- 关于模式对话框的问题?
- 问一个很菜的问题:为什么我们一敲就会出来汉字,这些汉字都存在什么地方?我想得到区位码的字库!
- Where to find a document to introduce the idc for IDA4.
- 如何到得到IHTMLWindow2 纯html文本
- 100分:IE全屏flash显示时会挡住ocx控件的显示
既然大部分页面好用,只能建议你多Debug一下。可能是网页构造跟你预想的不一样。
最好看看那个页面的Html文,然后debug一下看看中间有没有你没预想到的转页。
很多页面会产生很多个BEFORENAVIGATE2事件,debug一下看看事件发生的时候是不是跟你预想的一样。个人觉得这个只能靠自己调试。外因太多了。