原文: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.
|
還有一種方法就是打開VC的工具OLEView,懶的敲字了,看圖吧:
我的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。
文件目錄:
我們來寫個測試頁面,代碼如下:
<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
彈出對話框:
選擇是:
呵呵,彈出計算值3。算是成功了一半。那爲什麼系統沒有提示下載控件呢?這是因爲VS在編譯的時候已經幫我們把控件註冊到系統中了。
那現在首要的問題,就是先解決上面那個是否允許activex運行的提示框。
在網上查了下資料,說是要實現ISafeObject接口。那好,我們下面就來實現:打開工程,找到CMyActiveXCtr類,雙擊打開文件:
在文件中添加引用:
#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);
效果如圖:
在工程目錄中切換到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);
}
效果如下圖,注意畫紅框的地方:
F7編譯以後,按前面的步驟重新發布。
打開測試頁面http://10.79.108.108/test.html,呵呵那個討厭的對話框消失了。
現在這個ActiveX是完全做好了,下一步我們來看看怎樣讓用戶下載安裝。
先在本地電腦測試:
因爲我們用VC編譯時,VC已經幫我們把ActiveX註冊到系統中了,所以我們想看到下載安裝畫面,先必須刪除註冊信息。
打開運行窗口,輸出regedit命令,查找我們的控件GUI: 743F39F2-E3A5-4550-A203-4A1CFAE9ABCF
我這裏找到三項,那全部刪除。
在打開測試頁面之前,我們還得做個工作,就是設置IE安全。打開IE工具->Internet選項,如果是局域網,設置本地Intrance,允許下載未簽名和已簽名的ActiveX。如果是外網,方法一樣。
現在打開測試頁http://10.79.108.108/test.html
成功彈出下載ActiveX對話框。
點擊安裝,程序正常運行。OK,我們已經成功了一半。
上面只是在本地測試成功。現在在其他計算機上訪問測試頁,不要忘了IE的安全設置。打開頁面後也是彈出上面的安裝界面。可是,點安裝後,程序無法正常運行。而且每次刷新頁面,安裝對話框總是彈出,很是鬱悶。
經過Baidu,又找到了方法。原來是其他計算機上沒有安裝我們activeX運行所需的庫文件。那我們就想辦法讓用戶把這用到的DLL全部下載。
那首先得知道我們的activeX用到了哪些庫。如下圖,打開VC的工具Depends
選擇我們的MyActiveX.ocx控件,如下圖:
那我們可以看到我們用到的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
保存後文件目錄如下:
用 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增加新的功能。敬請關注。
呵呵,好累啊~~~~
打完收工…………………….