首先,想要在客户端直接执行服务器端的程序,必须做一个ActiveX控件(或者有个打包好的CAB文件也行),为的是能够用网页object。看到以前有高手说过,可以写一个没有任何功能的ActiveX控件,小的认为,如果这样的话,客户机的IE安全设置级别高的话,这个ActiveX控件就很难运行。如果想突破安全级别的限制的话,就必须在控件上下功夫。至于能突破安全级别的控件如何编写,小的在后面再介绍。
其实想直接运行安装程序,也可以不要ActiveX控件,只要一个安装文件就行(和匹配的INF文件),但是,如果这样,就必须使客户机的安全级别降到最低,或者把IE中安全选项:下载未签名的ActiveX,改成启用/提示。
假设现在我们有一个控件了(DLoad.ocx),除了你想在客户机上运行的Setup.exe文件我们还需要一个Setup.inf文件。这个inf文件如何编写,请看下面的例子:
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Add.Code]
DLoad.ocx=DLoad.ocx
mfc42.dll=mfc42.dll
msvcrt.dll=msvcrt.dll
olepro32.dll=olepro32.dll
setup.exe=setup.exe
[DLoad.ocx]
file-win32-x86=thiscab
clsid={68ADAF59-76C1-4561-A45A-867F43545237}
FileVersion=1,0,0,1
RegisterServer=yes
[msvcrt.dll]
FileVersion=6,0,8168,0
hook=mfc42installer
[mfc42.dll]
FileVersion=6,0,8168,0
hook=mfc42installer
[olepro32.dll]
FileVersion=5,0,4261,0
hook=mfc42installer
[mfc42installer]
file-win32-x86=VALUE=mfc42.cab
run= %EXTRACT_DIR% \mfc42.exe
[dotnetfx.exe]
file=thiscab
RegisterServer=yes
[Setup Hooks]
hook=setup
[setup]
run=%EXTRACT_DIR%\setup.exe
以上控件是使用Visual C++6.0编写的
这里需要说明的是上述msvcrt.dll、mfc42.dll、olepro32.dll的FileVersion是根
据VC不同的版本而异的,例如在VC5.0sp3中就应该如下
olepro32.dll 5,0,4230,1
mfc42.dll 4,21,0,7303
msvcrt.dll 5,0,0,7303
每个VC版本都有不同的版本号,这里只介绍常见的两种。
这里的clsid是从那得到的呢?是在你生成OCX的目录中.odl文件中得到的,注意,
打开这个文件后,我们可以看到四个clsid,最上面那个带有Version值的才是我们
需要的。这个clsid非常重要,它最终会注册到注册表里,提供版本的验证功能。只
有当程序发现你的注册表里没有这个clsid的时候,它才会自动安装。如果你安装了
一次,再安装一次的话,安装包(CAB)会发现注册表里有了这个clsid,它就不会
重复安装了。在mfc42installer里的mfc42.cab文件是需要下载的,下载地址:
http://activex.microsoft.com/controls/vc/mfc42.cab
另外mfc42installer的下载路径除了VC4.1和更早版本使用
http://activex.microsoft.com/controls/vc/mfc40.cab外,其他版本都使用
http://activex.microsoft.com/controls/vc/mfc42.cab。
下载完之后,把这个文件放在你的执行目录下就行了。
在这个inf例子中,包含了DLoad.ocx和setup.exe两个文件的信息。如果只单纯
执行OCX文件,他有关setup.exe的信息剔除就行了。
我们的inf文件编写完成,下面我们就要进行最重要的一步工作,把这些文件打
包成一个CAB文件。可以用VB和VS7.0自带的打包工具。不过我推荐使用WinCAB。这
个工具网上到处都有下载,不过下载安装完成之后,必须把Makecab.exe拷贝到
WinCAB的安装目录下才可运行,Makecab.exe文件在C:\WINNT\system32里。
CAB工具的使用方法:
(1)启动WinCAB,然后执行"Cabinet"菜单的"New"命令或单击快捷工具栏上的
"New cabinet"按钮,准备制作新的CAB压缩包。
(2)单击快捷工具栏上的"Add file(s) to cabinet"按钮,打开"Add file(s)
to cabinet"对话框。
(3)选择欲添加到CAB压缩包中的文件后单击"打开"按钮,将它们添加到WinCAB
的文件列表中。这里只需要添加YourCtl.ocx和YourCtl.inf两个文件。
(4)在WinCAB快捷工具栏的"Cabinet path and name"框中输入或利用"Browse
for path and name"按钮指定CAB压缩包的路径及文件名。
(5)在"Cabinet size"栏中指定CAB压缩包的尺寸。
(6)在"Compression method"框中选择合适的压缩方式。
(7)单击"Save cabinet"按钮,WinCAB即会按照用户的要求进行压缩。
(8)压缩完成后,WinCAB会给出一个"WinCAB Report"的报告框,向广大用户报
告有关文件个数、压缩前后的文件尺寸、压缩率、压缩时间等情况。至此,一个CAB
文件就生成了。
打包完成之后,我们要在网页中调用它了。
<OBJECT classid=clsid:68ADAF59-76C1-4561-A45A-867F43545237
codeBase=http://127.0.0.1/web/setup.cab#version=1,0,0,0>
<PARAM NAME="Setup" VALUE="http://127.0.0.1/web/DLoad.ocx">
</OBJECT>
现在可以马上进行测试,不过要把IE中的安全选项:下载未签名的ActiveX,改成启
用/提示。最好找台没有装3721上网助手(类似软件)的机器上测试。
以上控件的执行有很大局限性,如果安全级别高的话,就很难通过。所以现在介绍
如何突破IE安全级别限制的控件编写。
要包括两个文件
#include "comcat.h"
#include "Objsafe.h"
// 本控件的CLSID,注册表用
const GUID CDECL CLSID_SafeItem =
{ 0x7AE7497B, 0xCAD8, 0x4E66, {
0xA5,0x8B,0xDD,0xE9,0xBC,0xAF,0x6B,0x61 } };
// 创建组件种类
HRESULT createComponentCategory(CATID catid, WCHAR* catDescription)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CocreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr;
// Make sure the HKCR\Component Categories\{..catid...}
// key is registered.
CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = 0x0409 ; // english
// Make sure the provided description is not too long.
// Only copy the first 127 characters if it is.
int len = wcslen(catDescription);
if (len>127)
len = 127;
wcsncpy(catinfo.szDescription, catDescription, len);
// Make sure the description is null terminated.
catinfo.szDescription[len] = ''\0'';
hr = pcr->RegisterCategories(1, &catinfo);
pcr->Release();
return hr;
}
// 注册组件种类
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
// Register your component categories information.
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CocreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister,
(void**)&pcr);
if (SUCCEEDED(hr))
{
// Register this category as being "implemented" by the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
}
if (pcr != NULL)
pcr->Release();
return hr;
}
// 卸载组件种类
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CocreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (SUCCEEDED(hr))
{
// Unregister this category as being "implemented" by the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
}
if (pcr != NULL)
pcr->Release();
return hr;
}
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
HRESULT hr;
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::updateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);
// 标记控件初始化安全.
// 创建初始化安全组件种类
hr = createComponentCategory(CATID_SafeForInitializing, L"Controls
safely initializable from persistent data!";
if (FAILED(hr))
return hr;
// 注册初始化安全
hr = RegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
// 标记控件脚本安全
// 创建脚本安全组件种类
hr = createComponentCategory(CATID_SafeForScripting, L"Controls
safely scriptable!";
if (FAILED(hr))
return hr;
// 注册脚本安全组件种类
hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
if (FAILED(hr))
return hr;
return NOERROR;
}
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
HRESULT hr;
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::updateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
// 删除控件初始化安全入口.
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
// 删除控件脚本安全入口
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
if (FAILED(hr))
return hr;
//////////////////////////
return NOERROR;
}
详细解决方案
关于从WEB服务器自动上载安装可执行性文件的方法
热度:101 发布时间:2012-08-03 00:12:14.0
相关解决方案