[转载]vc6开发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增加新的功能。敬请关注。
呵呵,好累啊~~~~
打完收工…………………….