VB封装DLL实例讲解accessexcelword代码保护.docx
《VB封装DLL实例讲解accessexcelword代码保护.docx》由会员分享,可在线阅读,更多相关《VB封装DLL实例讲解accessexcelword代码保护.docx(23页珍藏版)》请在冰豆网上搜索。
VB封装DLL实例讲解accessexcelword代码保护
VB封装DLL实例讲解(一讲)
DLL基本概念
(一)概念
DLL即动态链接库(DynamicLinkLibrary),是由可被其它程序调用的函数集合组成的可执行文件模块。
DLL不是应用程序的组成部分,而是运行时链接到应用程序中。
(二)主要优点:
1、多个应用程序可以共享一个DLL,而且当多个应用程序调用库的同一个函数时,可执行文件中装入的只是该函数的内存地址,从而节省内存和磁盘空间;
2、使用动态链接库易于我们维护用户程序,即使对动态链接库进行修改也不会影响用户程序;
3、从ACCESS角度而言,还可以更好的确保核心代码的安全。
二、 用VB封装VBA代码,构建自定义的DLL动态链接库
(一)ACCESS中实例代码
下面是一个“快速获取数字(Acc).mdb”实例(该实例在文件包中),单击“提取结果”按钮,将文本框中的数字在弹出消息显示出来。
我将就这个实例演示如何将该实例VBA代码封装成为DLL。
?
按钮单击事件代码如下:
PrivateSubCmdFindnumber_Click()
DimstrM AsString '初始字符串
DimstrOut AsString '输出字符串变量
DimI
strM=Me.Text1
'从第一个字符向最后一个字符循环,以提取每个字符
ForI=1ToLen(strM)
'判断是否为0到9字符,是则赋值输出
IfMid(strM,I,1)Like"[0-9]"Then
strOut=strOut&Mid(strM,I,1)
EndIf
NextI
'用MsgBox函数进行输出测试
MsgBoxstrOut
EndSub
M以上代码还不能直接用于封装,须将其修改成为公用函数(过程)
(二)VB封装实例中VBA代码
步骤一:
在VB编辑窗中,点菜单【文件】-【新建工程】,打开新建工程窗口
步骤二:
修改工程名,这即生成的DLL库名
1、修改工程名为:
我的动态库
步骤三:
修改类名
1、改类名为:
提取数字
步骤四:
在代码窗口输入如下代码。
将ACCESS中的单击事件代码,略做修改成为一个公用函数,然后复制到VB代码编辑窗口
?
代码如下
'将这前的ACCESS代码改成一个公用函数
'输入:
strPutString字符串变量,需分离数字的字符串
'输出:
fFindNumber字符串变量,得到的数字字符
PublicFunctionfFindNumber(strPutStringAsString)AsString
DimstrOut AsString '输出字符串变量
DimI
'从第一个字符向最后一个字符循环,以提取每个字符
ForI=1ToLen(strPutString)
'判断是否为0到9字符,是则赋值输出
IfMid(strPutString,I,1)Like"[0-9]"Then
strOut=strOut&Mid(strPutString,I,1)
EndIf
NextI
'数字输出
fFindNumber=strOut
EndFunction
步骤五:
编译DLL,点菜单【文件】-【生成我的动态库.dll】,VBA代码封装DLL就完成了。
三、 在mdb中调用自定义DLL动态链接库
(一)新建数据库及窗体
新建【快速提取数字(DLL)实例.mdb】数据库,新建一个窗体【frmMain】,在窗体添文本框【text0】,按钮【CmdFindNum】,Caption属性:
“提取数字”(见下图)
(二)引用【我的动态库.dll】库
按【Alt+F11】打开VBE窗口,点菜单【工具】-【引用】,打开引用对话框,完成对我们自己编译的DLL的引用。
(三)在【CmdFindNum】按钮单击事件中加入如下代码。
PrivateSubCmdFindNum_Click()
'申明自定义类
DimMyFindNumAs提取数字
DimstrOutAsString
'实例化"提取数字类"对象
SetMyFindNum=New提取数字
'将函数输出结果赋值给自定义字符串变量
strOut=MyFindNum.fFindNumber(Text0)
'在消息框中显示
MsgBox"你提取的数字为:
"&strOut,vbInformation,"江羽提示:
"
EndSub
点击保存后,你就可以运行一下窗体测试你的成果了
M本文实例见实例包,下载测试如果提示错误,请重新对自定义类库进行引用。
本文只是通过一个简单的实例演示了,如何通过VB封装一般的VBA中代码,因为该代码中并未涉及到ACCESS应用程序对象,所以在VB中没有对ACCESS对象类库进行引用,另外实例中只是简单演示了,如何手动实现对DLL的注册引用,在后续文章中我将就如何实现DLL与ACCESS应用程序对接及DLL的自动注册及引用结合实例进行讲解。
VB封装DLL实例讲解(二讲)
上文中我们已经就DLL的基本概念,以及如何将VBA代码封装为DLL,如何引用该生成的DLL动态链接库,进行了初步的讲解,我想大家对于VB封装DLL应该有了一个初步的了解。
下面主要就DLL如何实现对ACCESS对象进行封装方法进行探讨。
一、如何在VB中实现对ACCESS对象编程
(一)在VB中引用ACCESS对象类库
我们要通过编译DLLACCESS对象的封装,首先必须在VB中引用ACCESS对象类库,这样我们就可以在VB中,实现对ACCESS应用程序中的对象进行编程。
来实现对
打开VB编辑窗口,点菜单【工程】-【引用】,打开【引用对话框】,点选“MicrosoftAccess11.0ObjectLibrary”完成对当前版本ACCESS应用程序对象的引用。
(实例演示版本为ACCESS2003)
M对ACCESS对象库的引用很关键,否则我们无法实现对ACCESS对象的编程
(二)了解ACCESS对象模型
在VB中要对ACCESS对象进行编程,还必需对ACCESS所提供的各项对象有一定了解,因为VB就是通过ACCESS对象的方法与属性,来完成各项操作与设置,下图为ACCESS2003的对象部分模型图例。
P上图为ACCESS2003对象模型,因为篇幅的问题,文中只显示模型中部分对象,要了解全部对象模型,请大家参阅帮助。
(三)VB编程中ACCESSVBA与VB对象表述区别
1、ACCESSVBA与VB的顶层对象都为Application,但在编程中ACCESSVBA顶层对象表述为:
Application,而在VB编程中顶层对象用简写:
App表述(到VB.NET又改回了Application)。
?
例程:
在VB编程中获得VB及ACCESSVBA获取当前路径实例:
'在VB中获得当前路径:
App.Path
'在VB中获得ACCESS的当前路径:
Application.CurrentProject.Path
P在office各应用程序之间调用各组件时,通常在对象前加上库名,如:
Access.Application来表述,但因为VB与ACCESS顶层对象原本表述就存在区别,在VB中可以直接用Application表述ACCESS应用程序对象,并不会产生冲突的问题。
2、ACCESSVBA和VB中部分预定义类对象(如:
窗体、控件等)表述基本相同,以“标签控件”为例,VB与ACCESSVBA均为Label,在VB编程中为了与ACCESS预定义类对象加以区别,ACCESS标签对象通常用ACCESS.Label表述。
?
例程:
在VB编程中定义VB及ACCESS标签控件对象实例:
'在VB中定义VB标签对象:
Dimm_LabelAsLabel
'在VB中定义ACCESS标签对象:
Dimm_LabelAsAccess.Label
M在进行DLL编程时,特别需注意对象表述区别的问题,否则无法编译或是编译后在ACCESS调用中报错。
(四)VB编程中关于ACCESSVBA专属常量
ACCESSVBA专属常量以“ac”开头,如:
控件类(AcControlType)中的文本控件常量为acTextBox,这些常量不一定能被VB所识别,解决办法通常不使用“常量名”,而直接使用“常量值”,或以输入参数方式传递的方法来解决。
?
例程:
实现隐藏所有文本控件。
acTextBox常量值为109。
Dimctl AsAccess.Control '申明ACCESS控件对象
DimfrmCltAsAccess.Controls '申明ACCESS控件集合
'遍历所有ACCESS控件集合,如为文本控件,则不显示该控件
ForEachctlInfrmClt.Controls
'文本控件类常量值为109,以常量值替代acTextBox常量名
Ifctl.ControlType=109Thenctl.Visible=False
Next
P你可以通过帮助查阅ACCESS专属常量值,也可以在ACCESSVBA中通过程序方式获取,如:
在立即窗口输入:
?
acTextBox回车,就可以acTextBox常量值为:
109。
二、DLL封装ACCESS对象实例演示
(一)ACCESS的MDB实例
MDB实例演示获得ACCESS版本信息,并在标签Label0中显示(见下图),具体参看实例中frmVer6窗体中的代码,及类模块ClsVeresion中代码。
Pmdb实例中frmVer1-frmVer6各窗体中具体演示了,代码按DLL封装需要整理的思路。
?
例程:
frmVer6窗体加载事件代码
PrivateSubForm_Load()
'申明自定义类的实例
Dimm_VerAsNewClsVeresion
'调用自定义类的objAddItem方法
m_Ver.objAddItemLabel0
EndSub
?
例程:
ClsVeresion类模块代码
'程序功能:
定义类接口,将版本信息输出并在标签中显示
PublicSubobjAddItem(m_labelAsLabel)
m_label.Caption=AppVersion
EndSub
'函数功能:
输出ACCESS版本信息
PrivateFunctionAppVersion()AsString
DimstrVerAsString'定义字符串变量
'将版本号赋值给字符串变量
strVer=Application.Version
'根据版号输出对应版本信息
SelectCasestrVer
Case"8.0"
AppVersion="Access97"
Case"9.0"
AppVersion="Access2000"
Case"10.0"
AppVersion="Access2002"
Case"11.0"
AppVersion="Access2003"
Case"12.0"
AppVersion="Access2007"
EndSelect
EndFunction
(二)DLL的封装ACCESS对象实现
1、打开VB6.0编辑器,点菜单【新建工程】,在【新建工程】对话框中,点选【ActiveXDLL】,点【确定】。
2、修改工程名及类名,实例中我定义的工程名:
GetAccVer,类名:
ClsAccVer,修改完成以后点选菜单【保存】工程(见下图)。
P工程名就是我们后面将引用的DLL库名,类模块名为代码中我们申明的类名。
3、点菜单【工程】-【引用】,打开【引用对话框】,点选“MicrosoftAccess11.0ObjectLibrary”完成对当前版本ACCESS应用程序对象的引用。
4、将MDB中类模块ClsVeresion代码复制到VB中ClsAccVer类模块中,按前面我们所述的VB中实现ACCESS对象编程的注意要点略做修改。
(见下图划红线部分)
P1、因为VB与ACCESSVBA中标签类对象都为Label,因此加上库名(Access.Label)加以区别;
2、因为VB与ACCESSVBA顶层应用程序对象,表述原本就有区别,所以无需特别区分。
?
例程:
ClsAccVer类模块代码
'程序功能:
定义DLL接口,将版本信息输出并在标签实例中显示
PublicSubobjAddItem(m_labelAsAccess.Label)
m_label.Caption=AppVersion
EndSub
'函数功能:
输出ACCESS版本信息
PrivateFunctionAppVersion()AsString
DimstrVerAsString'定义字符串变量
'将版本号赋值给字符串变量
strVer=Application.Version
'根据版号输出对应版本信息
SelectCasestrVer
Case"8.0"
AppVersion="Access97"
Case"9.0"
AppVersion="Access2000"
Case"10.0"
AppVersion="Access2002"
Case"11.0"
AppVersion="Access2003"
Case"12.0"
AppVersion="Access2007"
EndSelect
EndFunction
4、编译DLL,点菜单【文件】-【GetAccVer.dll】动态链接库,封装DLL就完成了。
你现在可以在ACCESS中引用该DLL测试一下看看成果了。
参看实例中frmVer7窗体,如实例引用报错,请重新引用GetAccVer.dll即可。
因为受本人认知及文字水平所限,不免有错漏之处,还请大家斧正。
本文的Word文稿、VB源码、MDB实例均在“实例包”中。
在后文中我们主要就动态链接库引用的方法和技巧结合实例进行探讨。
VB封装DLL实例讲解(三讲)
一、手动注册及引用
(一)手动注册及引用方法(参看实例:
手动引用.mdb)
进入VBA编辑窗口,点菜单【工具】—【引用】,打开【引用】对话框,点【浏览】按钮,打开【添加引用】对话框,点选要引用的DLL(测试实例为:
ClsFindString.dll),点【打开】—点【确定】,我们完成动态链接库的手动注册及引用。
(二)手动注册及引用方法不足及问题
手动注册引用优点是不言而喻的,方便简捷,易于操作。
但在实际运用中,当我们在其他电脑上发布应用程序,或运行我们测试好的应用程序时,却会出现错误提示,程序无法正常运行。
错误
(一):
找不到工程或库(见下图)
错误的主要原因:
DLL在当前运行的电脑系统中没有注册信息,而且引用不正确。
错误
(二):
引用的动态链接库(DLL)丢失(见下图)
进入到VBA编辑窗口,点菜单【工具】—【引用】,打开【引用】对话框,我们会看到之前引用的DLL动态链接库丢失。
错误的主要原因:
系统无法找到原路径引用DLL。
错误(三):
自动化错误(见下图)
错误的主要原因:
我们在发布应用程序的电脑或系统中,虽然重新完成DLL手动注册和引用,但如果DLL路径再次改变,运行程序时就会出现“自动化错误”提示。
错误(四):
ActiveX部件不能创建对象(见下图)
错误的主要原因:
应用程序已正常引用DLL动态链接库,但其册注信息丢失或者没有正常注册,就会出现以下问题。
(三)解决上述错误方法
1、解决错误方法,当然是重新进行DLL的手动注册及引用,具体步骤参下图。
但这只是治标不治本的办法,不利于对外发布我们的应用程序,最好的办法还是通过VBA自动完成DLL的注册及引用。
二、自动注册及引用方法
在探讨如何实现DLL自动注册及引用之前,我们必须清楚一点,那就是DLL的注册与引用并不是同一事件或行为的两种不同表述,而是两种不同的动作。
² DLL注册
是指将DLL的相关信息,如:
DLL唯一识标号(GUID),版本号(Version)及路径(Path)信息写入注册表中,以供系统对DLL进行识别调用。
我们通过VB编译生成DLL时,VB一般会自动完成对该DLL的注册,但如果要在其它电脑上运行程序时,我们就必须重新对该DLL进行注册。
² DLL引用
是指将DLL类库对象集成到代码编辑环境中,以便编程时调用类库中的对象、属性及方法。
我们通过手动方式完成DLL的引用时,系统会自动完成对该DLL的注册,所以我们无需另行对DLL进行注册,但如果我们在其它电脑上运行程序时,还会出现我们在之前章节中所述的错误。
(一)DLL自动注册方法
我们可以通过Regsvr32.exe来进行DLL注册或反注册,具体的语法及参数:
语法:
Regsvr32[/u][/n][/i[:
cmdline]]dllname
说明:
其中dllname为DLL文件名,建议在发布时将DLL复制到system文件夹下。
参数:
参数
说明
/u
反注册
/s
指定regsvr32安静运行,且不显示任何消息框。
/n
指定不调用DllRegisterServer。
此选项必须与/i共同使用。
/i:
cmdline
调用DllInstall将它传递到可选的[cmdline]。
在与/u共同使用时,它调用dll卸载。
dllname
指定要注册的dll文件名。
1.1示例通过Shell运行Regsvr32程序完成DLL注册
Shell"Regsvr32/S"&Chr(34)&CurrentProject.Path&"\ClsFindString.dll"&Chr(34)
Shell函数 用以运行Regsver32程序
Regsver32 注册程序
/S 注册程序参数,书写时记得参数前后必须留空
Chr(34) Chr函数,获指定代码字符,Chr(34)为引号
CurrentProject.Path DLL当前路径
ClsFindString.dll 演示实例DLL名
1.2示例通过Shell运行Regsvr32程序反注册
Shell"Regsvr32/U/S"&Chr(34)&CurrentProject.Path&"\ClsFindString.dll"&Chr(34)
我们可以将注册语句放在窗体的加载事件,自动完成DLL的注册,具体可以参看实例。
但如果我们有多个DLL需要批量注册时,可以考虑通过软件打包发布工具来完成DLL的注册工作;也可以事先编写BAT文件,在打包发布时将该BAT文件一并打包发布,安装时运行该BAT文件,来完成N个DLL的批量注册,在此就不多着笔墨,大家可以参看实例包中的BAT文件实例。
(二)DLL自动引用方法
2.1通过References对象的AddFromFile方法实现自动引用
DimrefAsReference '申明引用类对象
OnErrorResumeNext '避免因重复引用造成的错误提示
'实例化引用对象,完成DLL的引用
Setref=References.AddFromFile(CurrentProject.Path&"\ClsFindString.dll")
为了避免因重复引用出现的错误,我们可以如上代码中加入Error语句,我们还可以在应用程序退出时,通过对References对象的Remove方法释放DLL或反引用。
DimrefAsReference '申明引用类对象
'实例化反引用对象
Setref=References("ClsFindString")
'移除引用指定类库
References.Removeref
说明:
根据本人实践,我个人倾向于使用Error语句,因为如果应用程序非正常退出,引用对象没有反引用成功,启动时就难免出现重复引用的错误问题。
2.2通过DLL唯一标识号实现自动引用
DimrefAsReference '申明引用类对象
OnErrorResumeNext '避免因重复引用造成的错误提示
'唯一标识号完成注册,需要DLL标识号,主版本号,次版本
Setref=References.AddFromGuid("{C5E340E2-C557-4852-AE83-5A0578B6863B}",1,0)
DLL的标识号是编译生成时就确定了的,这个标识号就是DLL的终生制身份证号,我们可以通过这个唯一标识号来完成DLL自动引用。
但此种方法必须具备两个条件,一是DLL已经成功注册,二是我们知道了该DLL的标识号、主版本号、次版本号。
2.2.1获取DLL标识号、主版本号、次版本号方法
DimrefAsReference '申明引用类对象
'实例化引用类库对象
Setref=Refer