.Net下通过CoGetClassObjectFromURL 安装 ActiveX控件

 
.Net下通过CoGetClassObjectFromURL 安装 ActiveX控件
 
 
1 CoGetClassObjectFromURL MSDN 上的说明
 
CoGetClassObjectFromURL Function
Returns a factory object for a given CLSID.
Syntax
HRESULT CoGetClassObjectFromURL(      
    REFCLSID rclsid,
    LPCWSTR szCodeURL,
    DWORD dwFileVersionMS,
    DWORD dwFileVersionLS,
    LPCWSTR szContentType,
    LPBINDCTX pBindCtx,
    DWORD dwClsContext,
    LPVOID pvReserved,
    REFIID riid,
    VOID **ppv
);
Parameters
rclsid
[in] CLSID of the Microsoft ActiveX object to be installed. If the value is CLSID_NULL, szContentType is used to determine the CLSID.
需要安装的 ClassID ,如果为空,则根据安装包里 Inf 文件信息进行安装。不过通常这样安装的时候会报错,但是基本上 ActiveX 都能安装上去。
szCodeURL
[in] Address of a string value that contains the full URL of the code for the ActiveX object.
AcitveX 的安装路径,路径除了 URL 格式外,本地文件路径格式也支持。
dwFileVersionMS
[in] Unsigned long integer value that contains the major version number for the object to be installed. If this value and the value for dwFileVersionLS are both 0xFFFFFFFF, the latest version of the code should always be installed. This means that Internet Component Download will always attempt to download new code.
在安装 AcitveX 的时候,需要通过传入的的版本号与以安装文件的版本号进行比对,如果传入的版本号大于文件的版本号,则需要重新下载 ActiveX 控件。
通常文件版本由 4 位数字组成 a,b,c,d 。例: 1,0,0,3 。这里的主版本由版本号的前两位 a b 数字组成,并使用 MAKELONG(b,a) 函数进行合并。对于下面的副版本,则通过 MAKELONG(d,c) 进行合并。
如果想每次安装都进行更新就将参数设为 0xFFFFFFFF ,实际上就是按照最大的版本号进行更新。
dwFileVersionLS
[in] Unsigned long integer value that contains the minor version number for the object to be installed. If this value and the value for dwFileVersionMS are both 0xFFFFFFFF, the latest version of the code should always be installed. This means that Internet Component Download will always attempt to download new code.
szContentType
[in] Pointer to a string value that contains the Multipurpose Internet Mail Extensions (MIME) type to be understood by the installed ActiveX object. If rclsid is CLSID_NULL, this string is used to determine the CLSID of the object to be installed. Note that this parameter is useful only when trying to download a viewer for a particular media type, when the MIME type of media is known but the CLSID is not.
pBindCtx
[in] Pointer to the bind context to use for downloading/installing component code. An implementation of IBindStatusCallback must be registered on this bind context before calling this function.
一个绑定有IbindStatuseCallback接口的对象,通常是用于显示ActiveX的安装进度。这个对象创建比较简单。按照提供的示例代码一步步完成即可。
dwClsContext
[in] Unsigned long integer value that specifies the execution context for the class object. This can be one of the values taken from the CLSCTX enumeration.
pvReserved
[in] Reserved. Must be set to NULL.
riid
[in] Reference identifier of the interface to obtain on the factory object. Usually this interface is IClassFactory.
ppv
[out] Address of an interface pointer for synchronous calls, or NULL otherwise.
Return Value
Returns one of the following values:

S_OK
The operation completed successfully and the ppv parameter contains the requested interface pointer.
ActiveX 已经安装过
E_NOINTERFACE
The requested interface pointer is not available.
MK_S_ASYNCHRONOUS
Component code will be downloaded and installed asynchronously. The client will receive notifications through the IBindStatusCallback interface registered on pBindCtx.
ActiveX 没有安装过,正在进行异步的安装,安装过程通过 IBindStatusCallback 的回调过程通知用户

 
Remarks
If no CLSID is specified (CLSID_NULL), this function chooses the appropriate CLSID for interpreting the MIME type specified in szContentType. If the desired object is installed on the system, it is instantiated. Otherwise, the necessary code is downloaded and installed from the location specified in szCodeURL.
CoGetClassObjectFromURL was designed to be used by MSHTML to retrieve the code for objects on a Web page. When the requested object is available for use on the user's computer, this function typically returns synchronously with a valid object reference. For objects that aren't available on the user's computer and need to be downloaded from szCodeURL, CoGetClassObjectFromURL will return asynchronously with MK_S_ASNYNCHRONOUS and notify the calling application through the IBindStatusCallback interface that was registered on pBindCtx.
Function Information

Stock Implementation
urlmon.dll
Custom Implementation
No
Header
Urlmon.h
Import library
Urlmon.lib
Minimum availability
Internet Explorer 4.0
Minimum operating systems
Windows NT 4.0, Windows 95

 
2 CoGetClassObjectFromURL .Net 封装
     
      说明:安装 ActiveX 代码是用 MSDN 上的例子程序改编而成的,其目是为了给 .net 程序安装 AcitveX 控件。例子程序可以以“ CoGetClassObjectFromURL ”为关键字进行搜索 MSDN 找到。
 
      2.1 .Net
      regActiveX 是一个封装了安装 AcitveX 控件的 .net 类,用托管 C ++编写(实际上是因为在调用 windows 资源的时候托管 C++ C# 方便)其主要功能是调用 CoGetClassObjectFromURL 函数去安装 AcitveX 控件。在类里还增加两个时间,用于通知用户当前的安装进度已经安装结果。
 
     CDownload 实现了 IBindStatusCallback 接口,在安装 ActiveX 的过程中实现安装函数异步安装时的回调功能。该函数为 C++ 代码。
StdAfx.h
#pragma  once

#define  VC_EXTRALEAN         //  Exclude rarely-used stuff from Windows headers

#include 
< afxwin.h >           //  MFC core and standard components
#include  < afxext.h >           //  MFC extensions

regActiveX.h

#pragma  once

#include 
" stdafx.h "
#include 
" string "

using   namespace  System;

namespace  RegActiveX
{

    
public  __delegate  void  OnProcessHandler( int  Progress,  int  ProgressMax,  int  StatusCode, System::String *  StatusText);
    
public  __delegate  void  OnStopBindingHandler( int  hrResult, System::String *  Error);

    __gc 
public     class  regActiveX:  public  System::Object
    {
    
private :

        regActiveX()
        {
            hwnd 
=  NULL;
        }

    
protected :

        
//     注册 ActiveX 控件,该函数为执行函数
         void  RegisterActiveX(wchar_t  *  classid, wchar_t  *  url,  int  v1,  int  v2,  int  v3,  int  v4);

    
public :

        regActiveX(System::IntPtr hWnd)
        {
            hwnd 
=  hWnd;
        }

        System::IntPtr hwnd;

        
void  RegisterActiveX(System::String  *  classid, System::String  *  url);
        
void  RegisterActiveX(System::String  *  classid, System::String  *  url,  int  v1,  int  v2,  int  v3,  int  v4);

        __event OnProcessHandler
*  OnProcess;
        __event OnStopBindingHandler
*  OnStopBinding;

        
void  onProcess( int  Progress,  int  ProgressMax,  int  StatusCode, System::String *  StatusText)
        {
            
if  (OnProcess)
                OnProcess(Progress, ProgressMax, StatusCode, StatusText);
        }

        
void  onStopBinding( int  hrResult, System::String *  Error)
        {
            
if  (OnStopBinding)
                OnStopBinding(hrResult, Error);
        }

    };
}

regActiveX.cpp

#include 
" stdafx.h "

#include 
" RegActiveX.h "
#include 
" DownLoad.h "
#include 
" urlmon.h "

#pragma  comment( lib, "Urlmon.lib" )
using   namespace  RegActiveX;

void  regActiveX::RegisterActiveX(System::String  *  classid, System::String  *  url,  int  v1,  int  v2,  int  v3,  int  v4)
{
    
using   namespace  System::Runtime::InteropServices;
    wchar_t
*  id  =  (wchar_t * )( void * )(Marshal::StringToHGlobalUni(classid));
    wchar_t
*  u     =  (wchar_t * )( void * )(Marshal::StringToHGlobalUni(url));
    RegisterActiveX(id, u, v1, v2, v3, v4);
}

void  regActiveX::RegisterActiveX(System::String  *  classid, System::String  *  url)
{
    
using   namespace  System::Runtime::InteropServices;
    wchar_t
*  id  =  (wchar_t * )( void * )(Marshal::StringToHGlobalUni(classid));
    wchar_t
*  u     =  (wchar_t * )( void * )(Marshal::StringToHGlobalUni(url));
    RegisterActiveX(id, u, 
0xFFFF 0xFFFF 0xFFFF 0xFFFF );
}

void  regActiveX::RegisterActiveX(wchar_t  *  classid, wchar_t  *  url,  int  v1,  int  v2,  int  v3,  int  v4)
{
    LPCLASSFACTORY pClassFactory;
    HRESULT hr;

    CLSID m_clsid;
    LPBINDCTX m_pBindContext 
=  NULL;
    LPBINDSTATUSCALLBACK m_pBindStatusCallback    
=  NULL;

    hr 
=  OleInitialize(NULL);
    USES_CONVERSION;
    CLSIDFromString(classid, 
& m_clsid);

    hr 
=  CreateBindCtx( 0 & m_pBindContext);

    BIND_OPTS bindopts;
    m_pBindContext
-> GetBindOptions( & bindopts);
    bindopts.grfFlags 
|=  BIND_MAYBOTHERUSER;
    m_pBindContext
-> SetBindOptions( & bindopts);

    
//     绑定回调函数
    CDownload  * download  =   new  CDownload( this );
    download
-> ExternalQueryInterface( & IID_IBindStatusCallback, ( void   ** ) & m_pBindStatusCallback);
    hr 
=  RegisterBindStatusCallback(m_pBindContext, m_pBindStatusCallback,  0 0 );

    
//     调用安装AcitveX的API函数
    hr  =  CoGetClassObjectFromURL(m_clsid, url, 
        MAKELONG(v2, v1),  MAKELONG(v4, v3), 
        NULL, m_pBindContext, 
        CLSCTX_INPROC_HANDLER 
|  CLSCTX_INPROC_SERVER,
        
0 , IID_IClassFactory, ( void   ** ) & pClassFactory);

    
//     如果ActiveX已经安装过,直接触发安装结束的事件
     if  (hr  ==   0 )    
        
if  (OnStopBinding)
            OnStopBinding(
0 , System::String::Empty);
}

int  main()
{
    
//     不要问我为什么有这个东西,我也不清楚,反正没这个东西编译器不让我编译过去
}


CDownLoad.h

#pragma  once
#include 
" RegActiveX.h "

#define  VC_EXTRALEAN         //  Exclude rarely-used stuff from Windows headers

#include 
< afxwin.h >           //  MFC core and standard components
#include  < afxext.h >           //  MFC extensions
// #include <afxdisp.h>         //  MFC OLE automation classes
// #ifndef _AFX_NO_AFXCMN_SUPPORT
// #include <afxcmn.h>             //  MFC support for Windows Common Controls
// #endif  //  _AFX_NO_AFXCMN_SUPPORT
#define  WM_ONSTOPBINDING WM_USER + 1001

/// //
//  CDownload command target

class  CDownload :  public  CCmdTarget
{
    DECLARE_DYNCREATE(CDownload)

    CDownload();           
//  protected constructor used by dynamic creation

    
//     在安装过程中,需要触发一些安装事件,因此需要有一个 regActiveX 对象
    gcroot < RegActiveX::regActiveX *>   active;
    
//  Attributes
public :
    CFormView
*  m_pView;
    CDownload(gcroot
< RegActiveX::regActiveX *>   act)
    {
        active 
=  act;
        hwnd 
=  (HWND)( void * )act -> hwnd;
    }

    
//  Operations
public :
    
virtual   ~ CDownload();   //  had to make the destructor public

    
//     显示安全提示时需要的句柄,这个不是必须存在的
    
//     到时候可以通过 active 来获取,这里独立出来只是为了方便而已。
    HWND hwnd;

    
//  Overrides
    
//  ClassWizard generated virtual function overrides
    
// {{AFX_VIRTUAL(CDownload)
    
// }}AFX_VIRTUAL

    
//  Implementation
protected :
    
//     virtual ~CDownload();

    
//  Generated message map functions
    
// {{AFX_MSG(CDownload)
    
//  NOTE - the ClassWizard will add and remove member functions here.
    
// }}AFX_MSG

    DECLARE_MESSAGE_MAP()

public :
    DECLARE_INTERFACE_MAP()

    
//  IBindStatusCallback
    BEGIN_INTERFACE_PART(BindStatusCallback, IBindStatusCallback)
        STDMETHOD(OnStartBinding)(DWORD grfBSCOption, IBinding
*  pbinding);
        STDMETHOD(GetPriority)(LONG
*  pnPriority);
        STDMETHOD(OnLowResource)(DWORD dwReserved);
        STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText);
        STDMETHOD(OnStopBinding)(HRESULT hrResult, LPCWSTR szError);
        STDMETHOD(GetBindInfo)(DWORD
*  pgrfBINDF, BINDINFO *  pbindinfo);
        STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC 
* pfmtetc, STGMEDIUM *  pstgmed);
        STDMETHOD(OnObjectAvailable)(REFIID riid, IUnknown
*  punk);
    END_INTERFACE_PART(BindStatusCallback)

        
//  IWindowForBindingUI
        BEGIN_INTERFACE_PART(WindowForBindingUI, IWindowForBindingUI)
            STDMETHOD(GetWindow)(REFGUID rguidReason, HWND
*  phwnd);
        END_INTERFACE_PART(WindowForBindingUI)
};

CDownLoad.cpp

#include 
" StdAfx.h "
#include 
" .download.h "
#
using   < mscorlib.dll >


IMPLEMENT_DYNCREATE(CDownload, CCmdTarget)

CDownload::CDownload()
{
    hwnd 
=  NULL;
}

CDownload::
~ CDownload()
{
}


BEGIN_MESSAGE_MAP(CDownload, CCmdTarget)
    
// {{AFX_MSG_MAP(CDownload)
    
//  NOTE - the ClassWizard will add and remove mapping macros here.
    
// }}AFX_MSG_MAP
END_MESSAGE_MAP()

BEGIN_INTERFACE_MAP(CDownload, CCmdTarget)
    INTERFACE_PART(CDownload, IID_IBindStatusCallback, BindStatusCallback)
    INTERFACE_PART(CDownload, IID_IWindowForBindingUI, WindowForBindingUI)
END_INTERFACE_MAP()

/// //
//  CDownload message handlers

STDMETHODIMP_(ULONG) CDownload::XBindStatusCallback::AddRef()
{   
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  pThis -> ExternalAddRef();
}   

STDMETHODIMP_(ULONG) CDownload::XBindStatusCallback::Release()
{   
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  pThis -> ExternalRelease();
}   

STDMETHODIMP CDownload::XBindStatusCallback::QueryInterface(REFIID iid, 
void **  ppvObj)
{   
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  (HRESULT)pThis -> ExternalQueryInterface( & iid, ppvObj) ;
}   

STDMETHODIMP CDownload::XBindStatusCallback::OnStartBinding(DWORD grfBSCOption, IBinding
*  pbinding)
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  S_OK;
}

STDMETHODIMP CDownload::XBindStatusCallback::GetPriority(LONG
*  pnPriority) 
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  E_NOTIMPL;
}

STDMETHODIMP CDownload::XBindStatusCallback::OnLowResource(DWORD dwReserved)
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  E_NOTIMPL;
}

STDMETHODIMP CDownload::XBindStatusCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)

    
//     触发 OnProcess 事件,通知用户当前 Activex 安装进度
     if  (pThis -> active)
    {            
        pThis
-> active -> onProcess(ulProgress,
                                                 ulProgressMax,
                                                 ulStatusCode,
                                                 szStatusText
? new  System::String(szStatusText):System::String::Empty         // 状态字符串,在给用户的时候,把NULL转为空串                                );
    }    
    
return  NOERROR;
}

STDMETHODIMP CDownload::XBindStatusCallback::OnStopBinding(HRESULT hrResult, LPCWSTR szError) 
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)

    
//     触发 OnStopBinding 事件,通知外层安装结束
    
//     如果hrResult为0,表示安装成功,并且szError为空
    
//     如果hrResult非0,表示安装失败,szError为安装失败原因
     if  (pThis -> active)
    {
            pThis
-> active -> onStopBinding(hrResult, 
                                                            szError
? new  System::String(szError):System::String::Empty);
    }
    
return  S_OK;
}

STDMETHODIMP CDownload::XBindStatusCallback::GetBindInfo(DWORD
*  pgrfBINDF, BINDINFO *  pbindinfo) 
{
     METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  S_OK;
}

STDMETHODIMP CDownload::XBindStatusCallback::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC 
* pfmtetc, STGMEDIUM *  pstgmed) 
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)
        
return  S_OK;
}

STDMETHODIMP CDownload::XBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown
*  punk) 
{
    METHOD_PROLOGUE(CDownload, BindStatusCallback)

        
if  (riid  !=  IID_IClassFactory  ||  punk  ==  NULL)
            
return  E_INVALIDARG;

    
// pThis->m_pView->PostMessage(WM_ONSTOPBINDING, (WPARAM)punk);

    
return  S_OK;
}

STDMETHODIMP_(ULONG) CDownload::XWindowForBindingUI::AddRef()
{   
    METHOD_PROLOGUE(CDownload, WindowForBindingUI)
        
return  pThis -> ExternalAddRef();
}   

STDMETHODIMP_(ULONG) CDownload::XWindowForBindingUI::Release()
{   
    METHOD_PROLOGUE(CDownload, WindowForBindingUI)
        
return  pThis -> ExternalRelease();
}   

STDMETHODIMP CDownload::XWindowForBindingUI::QueryInterface(REFIID iid, 
void **  ppvObj)
{   
    METHOD_PROLOGUE(CDownload, WindowForBindingUI)
        
return  (HRESULT)pThis -> ExternalQueryInterface( & iid, ppvObj) ;
}   

STDMETHODIMP CDownload::XWindowForBindingUI::GetWindow(REFGUID rguidReason, HWND
*  phwnd)
{
    METHOD_PROLOGUE(CDownload, WindowForBindingUI)

    
//     如果希望在安装之前弹出安全提示,需要传入安装程序窗体的句柄

    
//     如果调用安装函数的时候,没有传入窗体句柄,并且 IE 对该下载ActiveX控件的地址没有设置为安全
    
//     则可能会出现安装失败,错误字符串: Generic trust failure.
     * phwnd  =  pThis -> hwnd;
    
return  S_OK;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值