VB動態呼叫外部函式的方法 (轉)
VB可以用Declare宣告來標準DLL的外部,但是其侷限性也很明顯:利用Declare我們只能載入在設計時透過Lib和Alias字句指定的函式指標!而不能在執行時指定由我們自己動態載入的函式指標),不能用Declare語句來呼叫任意的函式指標。當我們想動態呼叫外部函式的時候,就必須考慮採用其他的輔助方法,來完成這個任務了。
在文章《/develop/read_article.?id=12882">VB真是想不到系列之三:VB指標葵花寶典之函式指標 》、《Matthew Curland的VB函式指標呼叫》、《》等文獻中對此問題都進行了一定程度上的討論,但是頭緒都很繁瑣,對我這樣的菜鳥還有點深奧,在資料搜尋過程中,找到透過在VB中調入匯序,比較簡便的實現了這個功能,下面就是實現原理:
1)使用LoadLibrary載入DLL;
2)GetProcAddress獲得函式指標;
以上兩步得到了預載入函式的指標,但是VB中沒有提供使用這個指標的方法。我們可以透過一段語言,來完成函式指標的呼叫!
3)透過組合語言,把函式的所有引數壓入堆疊,然後用Call待用函式指標就可以了。
實現以上功能的主要:
'載入Dll
LibAddr = LoadLibrary(ByVal "user32")
'獲得函式指標
ProcAddr = GetProcAddress(LibAddr, ByVal "MessageBoxA")
'原型為MessageBox(hWnd, lpText, lpCaption, uType)
'---以下為Assembly部分---
push uType
push lpCaption
push lpText
push hWnd
call ProcAddr
'--------------------
FreeLibrary LibAddr'釋放空間
嘿,夠簡單吧!下面是動態呼叫MessageBoxA的,上面的步驟被封裝到RunDll32函式中,可放到模組(CallbyName.bas)中:
Dim s1() As Byte, s2() As Byte
Dim ret As Long
s1 = StrConv("Hello~World", vbFromUnicode)
s2 = StrConv("VBNote", vbFromUnicode)
ret = RunDll32("user32", "MessageBoxA", hwnd, Vtr(s1(0)), VarPtr(s2(0)), 0&)
CallAPIbyName.bas中的原始碼:
Option Explicit
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private 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
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lp As Any, ByVal cBytes As Long)
Public m_opIndex As Long '寫入位置
Private m_OpCode() As Byte 'Assembly 的OPCODE
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
AdyteToCode &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
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993192/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用動態建立自動化介面實現VB的函式指標呼叫 (轉)函式指標
- 外部函式的呼叫函式
- VB中呼叫WebService上的函式的方法Web函式
- VB呼叫C程式的方法—動態連結庫法 (轉)C程式
- httprunner yml 呼叫外部函式HTTP函式
- 走近VB.Net(二) 再談函式呼叫 (轉)函式
- 在PowerBuilder中動態呼叫函式UI函式
- 透過使用型別庫提高VB呼叫DLL函式的效能 (轉)型別函式
- 動態呼叫python類和函式Python函式
- VB呼叫API函式使視窗保持在最上層 (轉)API函式
- DELPHI中的靜態虛擬及動態方法函式的區別。 (轉)函式
- Python 外部函式呼叫庫ctypes簡介Python函式
- 走近VB.NET十六 SendKeys方法與Shell函式 (轉)函式
- C++原始碼免殺之函式的動態呼叫C++原始碼函式
- static函式塊中如何呼叫外部xml引數?函式XML
- 淺談API函式呼叫的方法API函式
- php呼叫mysql儲存過程和函式的方法(轉)PHPMySql儲存過程函式
- VB下幾個非常有用的函式 (轉)函式
- vb呼叫儲存過程的方法儲存過程
- JS函式的定義與呼叫方法JS函式
- 如何動態載入外部樣式表
- perl根據函式名動態呼叫函式
- 應用呼叫驅動的ioctl函式函式
- 外部js呼叫vue的methods中的方法JSVue
- JNI呼叫c動態連結庫函式程式碼實踐函式
- VS中呼叫DLL動態庫的方法
- 函式的動態引數 及函式巢狀函式巢狀
- vb如何使用ftp函式,vb如何使用ftp函式要知道這些FTP函式
- Vb下呼叫Help檔案 (轉)
- [轉載]論函式呼叫約定函式
- 在VB中實現窗體的動態效果 (轉)
- Python中動態類和動態方法的建立與呼叫Python
- Guru of the Week 條款27:轉呼叫函式 (轉)函式
- 呼叫類庫函式的簡單加密(轉的)函式加密
- Henry的VB.NET之旅(十五)—動態事件處理方法事件
- 深入探討Function Calling:實現外部函式呼叫的工作原理Function函式
- 利用VB的函式快速破解VB程式! (2千字)函式
- Transact-SQL 示例 - 如何在拼接的動態sql內呼叫外部變數SQL變數