⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vb-dll.txt

📁 介绍VB写标准DLL的方法
💻 TXT
📖 第 1 页 / 共 2 页
字号:

strCmd = Command

strPath = App.Path

Set ts = oFS.CreateTextFile(strPath & "\lnklog.txt")

ts.WriteLine "Beginning execution at " & Date & " " & Time()
ts.WriteBlankLines 1
ts.WriteLine "Command line parameters to LINK call:"
ts.WriteLine " " & strCmd
ts.WriteBlankLines 1
ts.WriteLine "Calling LINK linker"

Shell "linklnk.exe " & strCmd
If Err.Number <> 0 Then
ts.WriteLine "Error in calling linker..."
Err.Clear
End If

ts.WriteBlankLines 1
ts.WriteLine "Returned from linker call"
ts.Close

End Sub
执行前,把原始link.exe改成linklnk.exe,上面代码编译为link.exe
这样,再执行上面ActiveX dll的编译,我们看到链接器的log文件内容如下:

Beginning execution at 12/11/2004 12:44:33 PM

Command line parameters to LINK call:
"C:\Program Files\Microsoft Visual Studio\VB98\Class1.OBJ" 
"C:\Program Files\Microsoft Visual Studio\VB98\Project1.OBJ" 
"C:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB" 
/ENTRY:__vbaS 
/OUT:"C:\Program Files\Microsoft Visual Studio\VB98\Project1.dll" 
/BASE:0x11000000 
/SUBSYSTEM:WINDOWS,4.0 /VERSION:1.0 
/DLL 
/INCREMENTAL:NO /OPT:REF /MERGE:.rdata=.text /IGNORE:4078 

Calling LINK linker

Returned from linker call

如果我们同c或者c++链接器比较命令行参数,不同之处一目了然。这里/DLL开关指定创建标准的windows dll,而且这里没有/DEF开关来指定模块定义(module definition .def)文件,用于列出dll的输出函数。(在C或者c++中,我们用语句来定义输出函数),vb不支持它,然而,生成.def文件就是定义一个库的输出。)接着,如果我们检查vb环境中ActiveX dll工程生成的文件,vb并没有生成.def文件。

创建windows dll

好了,检查了ActiveX dll的输出表后,截获vb的编译,截获vb的链接,并同C和C++比较了传递给链接器的参数,我们可以识别出为什么在vb中创建真正的windows dll。不过用下面的办法,我们还是可以做到创建windows dll的。

1。给我们的工程创建一个.def文件,我们能够用不同的方法在.def文件中指定输出的函数,不过最好的就是简练:

NAME MathLib
LIBRARY MathMod
DESCRIPTION "Add-on Library of Mathematical Routines"
EXPORTS DllMain @1
Increment @2
Decrement @3
Square @4

Name语句定义了dll的名字,Library语句必须在输出函数之前。.def文件中同样要列举出函数在.bas文件的原始位置顺序,并用@符号。

2。决定我们要怎样截获调用链接器。主要用下面的技术来做:
创建一个代理链接器来截获调用真正的链接器,改变传递给链接器的命令行参数,并调用链接器来完成链接.上面我们已经说过相关技术了.

创建代理链接器,为了能生产其它文件,我们应该从有效性和方便性上考虑.
我们要在代理链接器的命令行参数中添加/DEF开关,后面跟上.def文件路径和文件名.接下来,在vb中创建标准exe工程,添加Microsoft Scripting Runtime Library引用,用工程中移除form,添加个模块.bas,代理链接器的代码如下:


Option Explicit

Public Sub Main()

Dim SpecialLink As Boolean, fCPL As Boolean, fResource As Boolean
Dim intPos As Integer
Dim strCmd As String
Dim strPath As String
Dim strFileContents As String
Dim strDefFile As String, strResFile As String
Dim oFS As New Scripting.FileSystemObject
Dim fld As Folder
Dim fil As File
Dim ts As TextStream, tsDef As TextStream

strCmd = Command

Set ts = oFS.CreateTextFile(App.Path & "\lnklog.txt")

ts.WriteLine "Beginning execution at " & Date & " " & Time()
ts.WriteBlankLines 1
ts.WriteLine "Command line arguments to LINK call:"
ts.WriteBlankLines 1
ts.WriteLine " " & strCmd
ts.WriteBlankLines 2

' Determine if .DEF file exists
'
' Extract path from first .obj argument
intPos = InStr(1, strCmd, ".OBJ", vbTextCompare)
strPath = Mid(strCmd, 2, intPos + 2)
intPos = InStrRev(strPath, "\")
strPath = Left(strPath, intPos - 1)
' Open folder
Set fld = oFS.GetFolder(strPath)

' Get files in folder
For Each fil In fld.Files
If UCase(oFS.GetExtensionName(fil)) = "DEF" Then
strDefFile = fil
SpecialLink = True
End If
If UCase(oFS.GetExtensionName(fil)) = "RES" Then
strResFile = fil
fResource = True
End If
If SpecialLink And fResource Then Exit For
Next

' Change command line arguments if flag set
If SpecialLink Then
' Determine contents of .DEF file
Set tsDef = oFS.OpenTextFile(strDefFile)
strFileContents = tsDef.ReadAll
If InStr(1, strFileContents, "CplApplet", vbTextCompare) > 0 Then
fCPL = True
End If

' Add module definition before /DLL switch
intPos = InStr(1, strCmd, "/DLL", vbTextCompare)
If intPos > 0 Then
strCmd = Left(strCmd, intPos - 1) & _
" /DEF:" & Chr(34) & strDefFile & Chr(34) & " " & _
Mid(strCmd, intPos)
End If
' Include .RES file if one exists
If fResource Then
intPos = InStr(1, strCmd, "/ENTRY", vbTextCompare)
strCmd = Left(strCmd, intPos - 1) & Chr(34) & strResFile & _
Chr(34) & " " & Mid(strCmd, intPos)
End If

' If Control Panel applet, change "DLL" extension to "CPL"
If fCPL Then
strCmd = Replace(strCmd, ".dll", ".cpl", 1, , vbTextCompare)
End If

' Write linker options to output file
ts.WriteLine "Command line arguments after modification:"
ts.WriteBlankLines 1
ts.WriteLine " " & strCmd
ts.WriteBlankLines 2
End If

ts.WriteLine "Calling LINK.EXE linker"
Shell "linklnk.exe " & strCmd
If Err.Number <> 0 Then
ts.WriteLine "Error in calling linker..."
Err.Clear
End If

ts.WriteBlankLines 1
ts.WriteLine "Returned from linker call"
ts.Close
End Sub
从代码中可以看出,代理链接器判断vb工程目录下是否有.def文件,如果有,就修改传递给链接器的命令行参数,添加/DEF开关到命令行,如果没有,则对传递给链接器的命令行参数不做任何改动.另外代理链接器还检测是否有资源文件也要被链接,最后,它还检测输出表中是否包含名字为CpApplet的函数,如果有,代理链接器修改输出文件的扩展名为.cpl(原来为.dll)

安装代理链接器,把vb自带的链接器命名为:LinkLnk.exe,把上面代理链接器代码编译,放到vb目录下,名为link.exe.
我们创建了代理链接器后,重新打开MathLib ActiveX dll工程,并选择编译为:Mathlib.dll

测试dll
我们创建了windows dll, 最后一步就是测试它是否工作正常,我们创建一个新的exe工程,并在模块中添加代码.注意声明的dll要在可找到的路径:
Option Explicit

Public Declare Function Increment Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
value As Integer) As Integer

Public Declare Function Decrement Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
value As Integer) As Integer

Public Declare Function Square Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
value As Long) As Long
在form的代码如下:


Option Explicit

Private Sub cmdDecrement_Click()
txtDecrement.Text = Decrement(CInt(txtDecrement.Text))
End Sub

Private Sub cmdIncrement_Click()
txtIncrement.Text = Increment(CInt(txtIncrement.Text))
End Sub

Private Sub cmdSquare_Click()
txtSquare.Text = Square(CLng(txtSquare.Text))
End Sub

Private Sub Form_Load()
txtIncrement.Text = 0
txtDecrement.Text = 100
txtSquare.Text = 2
End Sub

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -