vc6開發activex併發布全攻略(二)

原文:http://flashaway.blog.163.com/blog/static/95624576200942211853685/

小南瓜餅(^^):http://blog.csdn.net/Ibznphone


簽名問題先關注:

http://blog.csdn.net/ibznphone/article/details/8066322

###########以下是針對上一篇我們自己開發的ActiveX發佈時出現的問題補充############

 

 

呵呵,不要以爲這樣發佈就會成功。

博文中說用工具查看我們自己開發的ActiveX控件GUID,但我的好像查看不了。

其實我們在vc工程中就能查看到。雙擊DMyActiveX接口類,

 

找到       [ uuid(743F39F2-E3A5-4550-A203-4A1CFAE9ABCF),

         helpstring("MyActiveX Control"), control ]

       coclass MyActiveX

       {

              [default] dispinterface _DMyActiveX;

              [default, source] dispinterface _DMyActiveXEvents;

       };

 

方法中743F39F2-E3A5-4550-A203-4A1CFAE9ABCF就是我們ActiveX的GUID.

 

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

還有一種方法就是打開VC的工具OLEView,懶的敲字了,看圖吧:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

我的MyActiveX.inf如下:

    [version]  

    signature="$CHINA$" 

    AdvancedINF=1.0 

     

    [Add.Code]  

    MyActiveX.ocx=MyActiveX.ocx  

    msvcr71.dll=msvcr71.dll  

    mfc71.dll=mfc71.dll  

    msvcp71.dll=msvcp71.dll

   

   [MyActiveX.ocx]  

   file=thiscab  

   clsid={743F39F2-E3A5-4550-A203-4A1CFAE9ABCF}  

   FileVersion=1,0,0,0 

   RegisterServer=yes  

    

   [msvcr71.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=7,10,3052,4 

    

   [mfc71.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=7,10,3077,0 

    

   [msvcp71.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=7,10,3077,0 

 

按照上面的方法,用cabarc -s 6144 n MyActiveX.cab msvcr71.dll mfc71.dll msvcp71.dll MyActiveX.ocx MyActiveX.inf命令製作好MyActiveX..cab。

文件目錄:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

我們來寫個測試頁面,代碼如下:

 

<object id='test1' codeBase='http://10.79.108.108/MyActiveX.cab#version=1,0,0,0' classid='clsid: 743F39F2-E3A5-4550-A203-4A1CFAE9ABCF ' height=0 width=0 ></object>

<script>

       a=test1.test(2,1);

       alert(a);

</script>

注意:鏈接IP改成你機子的IP

將它保存爲test.html格式存放到IIS下,同時把MyActiveX也拷貝到IIS下,也就是C:\Inetpub\wwwroot下。

打開頁面測試下:

http://10.79.108.108/test.html

彈出對話框:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

選擇是:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

呵呵,彈出計算值3。算是成功了一半。那爲什麼系統沒有提示下載控件呢?這是因爲VS在編譯的時候已經幫我們把控件註冊到系統中了。

那現在首要的問題,就是先解決上面那個是否允許activex運行的提示框。

在網上查了下資料,說是要實現ISafeObject接口。那好,我們下面就來實現:打開工程,找到CMyActiveXCtr類,雙擊打開文件:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

在文件中添加引用:

#include "comcat.h"

#include "Objsafe.h"

兩個頭文件。

並在DECLARE_DYNCREATE(CMyActiveXCtro)後添加如下代碼:

DECLARE_INTERFACE_MAP()

       BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)

       STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (

               /* [in] */ REFIID riid,

               /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,

               /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions

       );

        

       STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (

               /* [in] */ REFIID riid,

               /* [in] */ DWORD dwOptionSetMask,

               /* [in] */ DWORD dwEnabledOptions

       );

       END_INTERFACE_PART(ObjSafe);

效果如圖:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

在工程目錄中切換到FileView模式,打開MyActiveXCtrl.cpp文件,

然後將以下代碼添加到構造函數CMyActiveXCtrl:: CMyActiveXCtrl ()上面,CMyActiveXCtrl替換爲你的控件名稱:

/////////////////////////////////////////////////////////////////////////////

// Interface map for IObjectSafety

 

BEGIN_INTERFACE_MAP( CMyActiveXCtrl, COleControl )

INTERFACE_PART(CMyActiveXCtrl, IID_IObjectSafety, ObjSafe)

END_INTERFACE_MAP()

 

/////////////////////////////////////////////////////////////////////////////

// IObjectSafety member functions

 

// Delegate AddRef, Release, QueryInterface

 

ULONG FAR EXPORT CMyActiveXCtrl::XObjSafe::AddRef()

{

    METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

    return pThis->ExternalAddRef();

}

 

ULONG FAR EXPORT CMyActiveXCtrl::XObjSafe::Release()

{

    METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

    return pThis->ExternalRelease();

}

 

HRESULT FAR EXPORT CMyActiveXCtrl::XObjSafe::QueryInterface(

    REFIID iid, void FAR* FAR* ppvObj)

{

    METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

    return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);

}

 

const DWORD dwSupportedBits =

INTERFACESAFE_FOR_UNTRUSTED_CALLER |

INTERFACESAFE_FOR_UNTRUSTED_DATA;

const DWORD dwNotSupportedBits = ~ dwSupportedBits;

 

/////////////////////////////////////////////////////////////////////////////

// CStopLiteCtrl::XObjSafe::GetInterfaceSafetyOptions

// Allows container to query what interfaces are safe for what. We're

// optimizing significantly by ignoring which interface the caller is

// asking for.

HRESULT STDMETHODCALLTYPE

CMyActiveXCtrl::XObjSafe::GetInterfaceSafetyOptions(

/* [in] */ REFIID riid,

        /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,

        /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)

{

METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

 

HRESULT retval = ResultFromScode(S_OK);

 

// does interface exist?

IUnknown FAR* punkInterface;

retval = pThis->ExternalQueryInterface(&riid,

     (void * *)&punkInterface);

if (retval != E_NOINTERFACE) { // interface exists

punkInterface->Release(); // release it--just checking!

}

 

// we support both kinds of safety and have always both set,

// regardless of interface

*pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;

 

return retval; // E_NOINTERFACE if QI failed

}

 

/////////////////////////////////////////////////////////////////////////////

// CStopLiteCtrl::XObjSafe::SetInterfaceSafetyOptions

// Since we're always safe, this is a no-brainer--but we do check to make

// sure the interface requested exists and that the options we're asked to

// set exist and are set on (we don't support unsafe mode).

HRESULT STDMETHODCALLTYPE

CMyActiveXCtrl::XObjSafe::SetInterfaceSafetyOptions(

        /* [in] */ REFIID riid,

        /* [in] */ DWORD dwOptionSetMask,

        /* [in] */ DWORD dwEnabledOptions)

{

    METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

 

// does interface exist?

IUnknown FAR* punkInterface;

pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);

if (punkInterface) { // interface exists

punkInterface->Release(); // release it--just checking!

}

else { // interface doesn't exist

return ResultFromScode(E_NOINTERFACE);

}

 

// can't set bits we don't support

if (dwOptionSetMask & dwNotSupportedBits) {

return ResultFromScode(E_FAIL);

}

 

// can't set bits we do support to zero

dwEnabledOptions &= dwSupportedBits;

// (we already know there are no extra bits in mask )

if ((dwOptionSetMask & dwEnabledOptions) !=

   dwOptionSetMask) {

return ResultFromScode(E_FAIL);

}       

 

// don't need to change anything since we're always safe

return ResultFromScode(S_OK);

}

效果如下圖,注意畫紅框的地方:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

F7編譯以後,按前面的步驟重新發布。

打開測試頁面http://10.79.108.108/test.html,呵呵那個討厭的對話框消失了。

現在這個ActiveX是完全做好了,下一步我們來看看怎樣讓用戶下載安裝。

先在本地電腦測試:

因爲我們用VC編譯時,VC已經幫我們把ActiveX註冊到系統中了,所以我們想看到下載安裝畫面,先必須刪除註冊信息。

打開運行窗口,輸出regedit命令,查找我們的控件GUI: 743F39F2-E3A5-4550-A203-4A1CFAE9ABCF

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

我這裏找到三項,那全部刪除。

在打開測試頁面之前,我們還得做個工作,就是設置IE安全。打開IE工具->Internet選項,如果是局域網,設置本地Intrance,允許下載未簽名和已簽名的ActiveX。如果是外網,方法一樣。

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

現在打開測試頁http://10.79.108.108/test.html

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

成功彈出下載ActiveX對話框。

點擊安裝,程序正常運行。OK,我們已經成功了一半。

 

上面只是在本地測試成功。現在在其他計算機上訪問測試頁,不要忘了IE的安全設置。打開頁面後也是彈出上面的安裝界面。可是,點安裝後,程序無法正常運行。而且每次刷新頁面,安裝對話框總是彈出,很是鬱悶。

經過Baidu,又找到了方法。原來是其他計算機上沒有安裝我們activeX運行所需的庫文件。那我們就想辦法讓用戶把這用到的DLL全部下載。

那首先得知道我們的activeX用到了哪些庫。如下圖,打開VC的工具Depends

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

選擇我們的MyActiveX.ocx控件,如下圖:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

那我們可以看到我們用到的DLL有6個,一般Kernel32.DLL和OLEAUT32.DLL文件每個操作系統都有,所以剩下的4個DLL,在你機子上全盤搜索,找到這4個dll後將他們放入你的MyActiveX.ocx相同文件夾下,編輯MyActiveX.inf, 這些dll的版本信息FileVersion可以在此dll上點擊右鍵->屬性中得到:

    [version]  

    signature="$CHINA$" 

    AdvancedINF=1.0 

     

    [Add.Code]  

    MyActiveX.ocx=MyActiveX.ocx  

    msvcr71.dll=msvcr71.dll  

    mfc71.dll=mfc71.dll  

    msvcp71.dll=msvcp71.dll

    MFC42D.dll=MFC42D.dll  

    MSVCRTD.DLL=MSVCRTD.DLL

    gdi32.dll=gdi32.dll

    MFCO42D.DLL=MFCO42D.DLL

 

   [MyActiveX.ocx]  

   file=thiscab  

   clsid={743F39F2-E3A5-4550-A203-4A1CFAE9ABCF}  

   FileVersion=1,0,0,0 

   RegisterServer=yes  

    

   [msvcr71.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=7,10,3052,4 

    

   [mfc71.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=7,10,3077,0 

    

   [msvcp71.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=7,10,3077,0 

 

   [MFC42D.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=6.0.9782.0

 

   [MSVCRTD.DLL]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=6.0.9782.0

 

   [gdi32.dll]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=5.2.3790.2542 

 

   [MFCO42D.DLL]  

   file-win32-x86=thiscab  

   RegisterServer=no  

   DestDir=11 

   FileVersion=6.0.9782.0

保存後文件目錄如下:

vc6開發activex併發布全攻略(二)(初級篇) - 一閃而過 - 一閃而過的博客

 

用 cabarc -s 6144 n MyActiveX.cab msvcr71.dll mfc71.dll msvcp71.dll MFC42D.dll MSVCRTD.DLL gdi32.dll MFCO42D.DLL MyActiveX.ocx MyActiveX.inf

命令生成MyActiveX.cab文件。

在其他計算機上打開測試頁。安裝ActiveX成功,並且運行正常。

就此,一個簡單的ActiveX發佈成功了。

後面,我們還將對我們的ActiveX增加新的功能。敬請關注。

呵呵,好累啊~~~~

打完收工…………………….

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章