能否不声明函数原型就调用外部DLL的函数?
一般情况下,必须在代码前部声明函数原型后,才能在后面调用,现在小弟碰到的问题是,能否在不声明函数的前提下,直接执行DLL中的函数。
小弟已经试过使用LoadLibrary,然后GetProcAddress,的方法,但是好像行不通。
请高手赐教!
[解决办法]
Option Explicit
Public Declare Function LoadLibrary Lib "kernel32 " Alias "LoadLibraryA " (ByVal lpLibFileName As String) As Long
Public Declare Function GetProcAddress Lib "kernel32 " (ByVal hModule As Long, ByVal lpProcName As String) As Long
Public Declare Function CallWindowProc Lib "User32 " Alias "CallWindowProcA " (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function FreeLibrary Lib "kernel32 " (ByVal hLibModule As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32 " Alias "RtlMoveMemory " (lpDest As Any, lpSource As Any, ByVal cBytes As Long)
Private m_opIndex As Long '写入位置
Private m_OpCode() As Byte 'Assembly 的OPCODE
Public Function DynamicRunDll32(ByVal isUnload As Boolean, ByVal strLibFileName As String, strProcName As String, ParamArray Params()) As Long
Dim hProc As Long
Dim hModule As Long
ReDim m_OpCode(400 + 6 * UBound(Params)) '保留用来写m_OpCode
'读取API库
hModule = LoadLibrary(ByVal strLibFileName)
If hModule = 0 Then
MsgBox "Library读取失败! "
DynamicRunDll32 = 0
Exit Function
End If
'取得函数地址
hProc = GetProcAddress(hModule, ByVal strProcName)
If hProc = 0 Then
MsgBox "函数读取失败! ", vbCritical
FreeLibrary hModule
DynamicRunDll32 = 0
Exit Function
End If
'执行Assembly Code部分
DynamicRunDll32 = CallWindowProc(GetCodeStart(hProc, Params), 0, 1, 2, 3)
'一些函数需要驻留这就先不释放
If isUnload Then FreeLibrary hModule '释放空间
End Function
'Public Function RunDll32(LibFileName As String, ProcName As String, ParamArray Params()) As Long
' Dim hProc As Long
' Dim hModule As Long
'
' ReDim m_OpCode(400 + 6 * UBound(Params)) '保留用来写m_OpCode
' '读取API库
' hModule = LoadLibrary(ByVal LibFileName)
' If hModule = 0 Then
' MsgBox "Library读取失败! "
' Exit Function
' End If
'
' '取得函数地址
' hProc = GetProcAddress(hModule, ByVal ProcName)
' If hProc = 0 Then
' MsgBox "函数读取失败! ", vbCritical
' FreeLibrary hModule
' Exit Function
' End If
'
'
' '执行Assembly Code部分
' RunDll32 = CallWindowProc(GetCodeStart(hProc, Params), 0, 1, 2, 3)
'
' FreeLibrary hModule '释放空间
'End Function
Private Function GetCodeStart(ByVal lngProc As Long, ByVal arrParams As Variant) As Long
'---以下为Assembly部分--
'作用:将函数的参数压入堆栈
Dim lngIndex As Long, lngCodeStart As Long
'程序起始位址必须是16的倍数
'VarPtr函数是用来取得变量的地址
lngCodeStart = (VarPtr(m_OpCode(0)) Or &HF) + 1
m_opIndex = lngCodeStart - VarPtr(m_OpCode(0)) '程序开始的元素的位置
'前面部分以中断点添满
For lngIndex = 0 To m_opIndex - 1
m_OpCode(lngIndex) = &HCC 'int 3
Next lngIndex
'--------以下开始放入所需的程序----------
'将参数push到堆栈
'由于是STDCall CALL 参数由最后一个开始放到堆栈
For lngIndex = UBound(arrParams) To 0 Step -1
AddByteToCode &H68 'push的机器码为H68
AddLongToCode CLng(arrParams(lngIndex)) '参数地址
Next lngIndex
'call hProc
AddByteToCode &HE8 'call的机器码为HE8
AddLongToCode lngProc - VarPtr(m_OpCode(m_opIndex)) - 4 '函数地址 用call的定址
'-----------结束所需的程序--------------
'返回呼叫函數
AddByteToCode &HC2 'ret 10h
AddByteToCode &H10
AddByteToCode &H0
GetCodeStart = lngCodeStart
End Function
Private Sub AddLongToCode(lData As Long)
'将Long类型的参数写到m_OpCode中
CopyMemory m_OpCode(m_opIndex), lData, 4
m_opIndex = m_opIndex + 4
End Sub
Private Sub AddIntToCode(iData As Byte)
'将Integer类型的参数写道m_OpCode中
CopyMemory m_OpCode(m_opIndex), iData, 2
m_opIndex = m_opIndex + 2
End Sub
Private Sub AddByteToCode(bData As Byte)
'将Byte类型的参数写道m_OpCode中
m_OpCode(m_opIndex) = bData
m_opIndex = m_opIndex + 1
End Sub
窗体源码:
Private Sub cmdOk_Click()
Call DynamicRunDll32(False, "test.dll ", "ShowMessage ")
End Sub
Private Sub Form_Load()
Dim s1() As Byte, s2() As Byte
Dim ret As Long
s1 = StrConv( "123 ", vbFromUnicode)
s2 = StrConv( "VBNote ", vbFromUnicode)
ret = DynamicRunDll32(True, "user32 ", "SetWindowTextA ", hWnd, VarPtr(s1(0)))
ret = DynamicRunDll32(True, "user32 ", "SetWindowTextA ", hWnd, StrPtr(s2))
Call DynamicRunDll32(True, "kernel32 ", "DeleteFileA ", StrPtr(StrConv( "c:\111.txt ", vbFromUnicode)))
End Sub