[原创]改造VB6,使其支持生成具有输出函数的dll
发表于:
2006-12-31 02:19
9450
[原创]改造VB6,使其支持生成具有输出函数的dll
【文章标题】: 改造VB6,使其支持生成具有输出函数的dll
【文章作者】: edisonH
【作者邮箱】: edison_h_cr@yahoo.com.cn
【软件名称】: VB 6.0
【下载地址】: 自己搜索下载
【编写语言】: VB 6.0
【操作平台】: WindowsXP sp1
【作者声明】: 没有什么技术,失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
使用VB6创建dll时,可选项为“ActiveX Dll”,这种dll只是com组件,不支持在dll中输出函数。其实VB生成最终的exe或dll目标文件是这样的:首先生成obj文件,然后调用link.exe链接成最终的exe或dll,然后删除obj。
网上很早就有人提出一种方法:将原来的link改名(如orgLink),然后写一个自己的link.exe,再去调用原来的link,如下
Private Sub Form_Load()
If (MsgBox("继续链接", vbOKCancel) = vbOK) Then
Shell "orgLink.exe " & Command
End If
End
End Sub
当MsgBox中断下来的时,把相关的obj文件拷出来,然后增加/EXPORT 开关手动链接来增加输出函数。
假设VB装在"F:\Program Files\VB6\"下
源码保存在"F:\Program Files\VB6\Project\TestDll\"下
我们看看VB自己链接时的链接代码是怎么样的,如下:
"F:\Program Files\VB6\Project\TestDll\Class1.OBJ" "F:\ProgramFiles\VB6\Project\TestDll\Module1.OBJ" "F:\Program Files\VB6\Project\TestDll\TestDll.OBJ" "F:\Program Files\VB6\VBAEXE6.LIB" /ENTRY:__vbaS /OUT:"F:\Program Files\VB6\Project\TestDll\TestDll.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERSION:1.0 /DLL /INCREMENTAL:NO /OPT:REF /MERGE:.rdata=.text /IGNORE:4078
那么增加/EXPORT 开关来增加输出函数的链接代码如下:
"F:\Program Files\VB6\Project\TestDll\Class1.OBJ" "F:\ProgramFiles\VB6\Project\TestDll\Module1.OBJ" "F:\Program Files\VB6\Project\TestDll\TestDll.OBJ" "F:\Program Files\VB6\VBAEXE6.LIB" /ENTRY:__vbaS /EXPORT:TestFunction /OUT:"F:\Program Files\VB6\Project\TestDll\TestDll.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERSION:1.0 /DLL /INCREMENTAL:NO /OPT:REF /MERGE:.rdata=.text /IGNORE:4078
可以看到上面链接命令中通过/EXPORT 开关增加了输出函数TestFunction。
但是手动链接比较麻烦,而通过/EXPORT 开关来编写可以增加输出函数的自动链接也不太方便。还好,link还有另一个开关可以批量增加输出函数--/DEF,可以这样使用:/DEF:"...\TestDll.def",
其中输出函数需要放到dll定义文件dll.def中,如下:
LIBRARY TestDll
EXPORTS TestFunction
LIBRARY 关键字是必须的,它定义了DLL的模块名称,必须和动态链接库的名称相同。
EXPORTS 关键字告诉链接器该DLL的输出函数,多个输出函数时可以重复使用关键字,如
LIBRARY TestDll
EXPORTS TestFunction0
EXPORTS TestFunction1
EXPORTS TestFunction2
......
这下明朗了,可以在源码目录下增加一个DLL.def文件(如果没有保存就生成目标dll,可将dll.def放在目标目录下),里面用关键字EXPORTS定义需要输出哪些函数,再通过/DEF开关来告诉链接器.
链接代码如下:
"F:\Program Files\VB6\Project\TestDll\Class1.OBJ" "F:\ProgramFiles\VB6\Project\TestDll\Module1.OBJ" "F:\Program Files\VB6\Project\TestDll\TestDll.OBJ" "F:\Program Files\VB6\VBAEXE6.LIB" /ENTRY:__vbaS /OUT:"F:\Program Files\VB6\Project\TestDll\TestDll.dll" /BASE:0x11000000 /SUBSYSTEM:WINDOWS,4.0 /VERSION:1.0 /DLL /DEF:"F:\Program Files\VB6\Project\TestDll\DLL.def" /INCREMENTAL:NO /OPT:REF /MERGE:.rdata=.text /IGNORE:4078
下面是一个完成上述工作的VB代码,把原来的link.exe改为orgLink.exe,下面代码生成为link.exe即可
Private Sub Form_Load()
Dim sCmdLine$, s1$, s2$,s3$,s4$, n1%, n2%, n3%, n4%
sCmdLine = Command
n1 = InStr(sCmdLine, "/DLL") ' 查找/DLL开关,确定目标文件是dll才决定是否增加输出函数
If n1 = 0 Then ' 目标文件是exe就直接调用orgLink
Shell "orgLink.exe " & Command
End
End If
n2 = InStr(sCmdLine, ".OBJ") ' 取DLL.def的目录。它与Class1.OBJ同一目录,所以取Class1.OBJ目录即可
s1 = Left(sCmdLine, n2 - 1)
n3 = Len(s1)
s2 = StrReverse(s1)
n4 = InStr(s2, "\")
s3 = Left(s1, n3 - n4 + 1)
s4 = " /DEF:" & s3 & "DLL.def" & Chr(&H22) ' /DEF:"F:\Program Files\VB6\Project\TestDll\DLL.def"
sCmdLine = sCmdLine & s4 ' 为方便起见,直接将/DEF:"...\DLL.def"插到命令行最后,不影响结果
Shell "orgLink.exe " & sCmdLine
End
End Sub
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年12月31日 2:05:33
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!