自动化浏览器时出了问题,没法解决。
捕获浏览器事件直接造成浏览器阻塞,除非断开事件连接,否则浏览器无法继续运行//iectrl.cpp
#include <windows.h>
#include ".\ieSink.h"
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
CoInitialize(NULL);
IWebBrowser2 *m_pInternetExplorer;
HRESULT hr;
CIESink ieSink;
hr=CoCreateInstance(CLSID_InternetExplorer,NULL,CLSCTX_SERVER,IID_IWebBrowser2,(LPVOID *)&m_pInternetExplorer);
m_pInternetExplorer->put_Visible(VARIANT_TRUE);
if(SUCCEEDED(hr))
{
ieSink.Connect(m_pInternetExplorer);//连接事件捕获
BSTR Url,Target,PostData,Head;
VARIANT BstrUrl,BstrTarget,IFlag,BstrPostData,BstrHead;
V_VT(&BstrUrl)=VT_BSTR;
V_BSTR(&BstrUrl)=Url=SysAllocString(L"http://www.baidu.com");
V_VT(&BstrTarget)=VT_BSTR;
V_BSTR(&BstrTarget)=Target=SysAllocString(L"_self"); V_VT(&BstrPostData)=VT_BSTR;
V_BSTR(&BstrPostData)=PostData=SysAllocString(L"_self");
V_VT(&BstrHead)=VT_BSTR;
//V_BSTR(&BstrHead)=Head=SysAllocString(L"Content-Type: application/x-www-form-urlencoded\r\n");
V_BSTR(&BstrHead)=Head=SysAllocString(L"");
V_VT(&IFlag)=VT_I4;
V_I4(&IFlag)=navNoHistory; m_pInternetExplorer->Navigate2(&BstrUrl,&IFlag,&BstrTarget,&BstrPostData,&BstrHead);
SysFreeString(Url);
SysFreeString(Target);
SysFreeString(PostData);
SysFreeString(Head);
}
system("pause");
ieSink.DisConnect();
return TRUE;
}//iesink.cpp
#include ".\iesink.h"CIESink::CIESink(void)
: m_pConnectionPoint(0)
, m_dwCookie(0)
{
}CIESink::~CIESink(void)
{
}STDMETHODIMP_(ULONG) CIESink::AddRef()
{
return E_NOTIMPL;;
}STDMETHODIMP_(ULONG) CIESink::Release()
{
return E_NOTIMPL;;
}STDMETHODIMP CIESink::QueryInterface(REFIID riid, LPVOID* ppv)
{
*ppv = NULL; if (IID_IUnknown == riid)
{
*ppv = (LPUNKNOWN)this;
return NOERROR;
}
else if (IID_IDispatch == riid)
{
*ppv = (IDispatch*)this;
return NOERROR;
}
else
return E_NOTIMPL;
}STDMETHODIMP CIESink::Invoke(DISPID dispIdMember,
  REFIID riid,
  LCID lcid,
  WORD wFlags,
  DISPPARAMS __RPC_FAR *pDispParams,
  VARIANT __RPC_FAR *pVarResult,
  EXCEPINFO __RPC_FAR *pExcepInfo,
  UINT __RPC_FAR *puArgErr)
{
ODS("invoke\n");
return NOERROR;
}STDMETHODIMP CIESink::Connect(IWebBrowser2 *pInternetExplorer)
{
IConnectionPointContainer *pCPContainer;
HRESULT hr=pInternetExplorer ->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPContainer);
if (SUCCEEDED(hr))
{
hr=pCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2,&m_pConnectionPoint);
pCPContainer->Release();
if(SUCCEEDED(hr))
{
hr=m_pConnectionPoint->Advise(this,&m_dwCookie);
}
}
return S_OK;
}STDMETHODIMP CIESink::DisConnect()
{
HRESULT hr = NOERROR;
if (m_pConnectionPoint)
{
if (m_dwCookie)
{
hr = m_pConnectionPoint->Unadvise(m_dwCookie);
m_dwCookie = 0;
}  m_pConnectionPoint->Release();
 m_pConnectionPoint = NULL;
}
return NOERROR;
}
//iesink.h
#pragma once
#include "oaidl.h"
#include <ExdispID.h>
#include <Exdisp.h>#define ODS(x) OutputDebugString(x)class CIESink :
public IDispatch
{
public:
CIESink(void);
~CIESink(void); // IUnknown methods
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv);
    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)();  // IDispatch method
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{ ODS("GetTypeInfoCount\n"); return E_NOTIMPL; } STDMETHOD(GetTypeInfo)(UINT iTInfo,
            LCID lcid,
            ITypeInfo** ppTInfo)
{ ODS("GetTypeInfo\n"); return E_NOTIMPL; } STDMETHOD(GetIDsOfNames)(REFIID riid,
            LPOLESTR* rgszNames,
            UINT cNames,
            LCID lcid,
            DISPID* rgDispId)
{ ODS("GetIDsOfNames\n"); return E_NOTIMPL; }
        
STDMETHOD(Invoke)(DISPID dispIdMember,
            REFIID riid,
            LCID lcid,
            WORD wFlags,
            DISPPARAMS __RPC_FAR *pDispParams,
            VARIANT __RPC_FAR *pVarResult,
            EXCEPINFO __RPC_FAR *pExcepInfo,
            UINT __RPC_FAR *puArgErr);    //this class
STDMETHOD(Connect)(IWebBrowser2 *pInternetExplorer);
STDMETHOD(DisConnect)();private:
// 连接点
IConnectionPoint *m_pConnectionPoint;
DWORD m_dwCookie;
};

解决方案 »

  1.   

    不需要消息循环阿?程序是控制ie的。只需要接受ie的消息就是了
      

  2.   

    你说的太抽象了,不明白。具体是哪里需要?我调试程序的时候程序自动变成多线程。就是说那事件处理是com自己开出线程的。至于那循环也应该再这里吧?麻烦你说具体些。谢谢了
      

  3.   

    When your STA thread is doing nothing else, it needs to be checking to see if any other threads want to marshal some calls into it.  This is done with a Windows message pump.  If the STA thread fails to pump, these incoming calls will be blocked.  If the incoming calls are GUI SendMessages or PostMessages (which I think of as synchronous or asynchronous calls respectively), then failure to pump will produce an unresponsive UI.  If the incoming calls are COM calls, then failure to pump will result in calls timing out or deadlocking.
    http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx
      

  4.   

    大体上了解了,但太多的名词都不清楚STA thread ??
    能帮忙把我的代码上需要补上的东西补上吗??我现在感觉无从下手!!!
    毕竟刚接触这些东西。谢谢了
      

  5.   

    问题应该不是你说的这个。下面这段是连接点模型的一个描述3. 构造伪异步COM服务器
    3.1伪异步COM服务器总体框架
    伪异步调用的实质是客户程序将一个自己所实现的接收器指针传递到COM服务器,当服务器的接口受到客户程序调用的时候将产生新的线程来实现功能任务,而客户程序的调用结束返回,新线程将在任务完成后通过传入的接口指针回调到客户程序,以通知客户程序当前调用服务的消息和结果,从而在客户程序和服务器之间产生一种对等关系。服务器和客户程序异步协商过程如下:
    1) COM实现一个服务器组件对象,它要么处在STA中,要么处在MTA中。
    2) 客户程序通过COM服务器的公开接口查询IConnectionPointContainer接口,客户查询成功就表明服务器支持连接点。
    3) 查询成功,客户程序使用上面接口的FindConnectionPoint()方法来定位特定的出接口;或者用EnumConnectionPoints()方法枚举所有连接点,再进行查询定位。这样客户程序可以获得一个IConnectionPoint接口,并通过它建立与服务器的连接。
    4) 定位成功,则由客户端实现这个出接口,这里的接口实现也即接收器(Sink)。
    5) 客户程序通过IConnectionPoint::Advise()方法将一个指向接收器的一个出接口指针传递给服务器。连接被建立。
    6) COM服务器收到调用请求,创建新线程,并由新线程通过这个收到的出接口指针进行回调(callback)操作,将通知或消息反馈到接收器,从而完成一次异步调用。
    这是一种非常常规的方法,为客户程序提供了一个标准的方法来实现这些接口,而且MFC(微软基本类库)和ATL(活动模板类库)都对连接点技术提供了很好的支持,使用方便。当然也能在服务器组件中直接使用出接口,从而省去出于标准化目的而对出接口进行的封装。这样的好处是服务器组件直观、高效,可以减少额外的开销,但是它不能为客户程序提供一个标准的方法来实现出接口,所以建议只在服务器和客户端配合开发,双方均了解出接口,且接口较为简单的情况下使用。
      

  6.   

    只用在STA才需要消息循环吧,MTA不需要的
    STA= single-threaded apartment
    MTA= multiple-threaded apartment