VB靜態調用與動態調用dll詳解

【【請注意】】:在以下語法格式中,請注意 [函數名] 的【大小寫】!!!

靜態與動態比較:

    靜態調用簡單,動態調用麻煩;靜態調用佔用資源多,動態調用佔用資源少;正所謂魚和熊掌不可兼得。


靜態調用定義:

    就是常用的申明API,一個DLL庫裏有很多的函數可供調用,把要用的申明即可。
    比如:Public/Private Declare Function [函數名] Lib "DLL文件名" [Alias "別名"] (參數變量表) [As 返回值的數據類型]
    示例:Private Declare Function Test Lib "dll.dll" (x As String) As String
    當程序結束的時候系統回自動釋放DLL調用。


動態調用定義:

    使用LoadLibery(DLL名),系統會檢查DLL是否調入內存。如果調入了,可直接調用DLL裏的所有函數,沒有就會把DLL加入目標進程的進程空間。通過函數GetProcAddress確定函數入口地址,然後調用,後一種方法VB裏不常用的。


靜態調用詳解:

    製作好DLL之後,首先用Declare聲明語句在窗體級或模塊級或全局模塊的代碼聲明段進行聲明,將動態鏈接庫中的函數聲明到VB中,供VB程序調用。

    語法格式1:
        Public/Private Declare Sub [函數名] Lib "DLL文件名" [Alias "別名"] (參數變量表)

    語法格式2:
        Public/Private Declare Function [函數名] Lib "DLL文件名" [Alias "別名"] (參數變量表) [As 返回值的數據類型]

    在聲明中首先用Declare關鍵字表示聲明DLL中的函數。在C語言中有的函數類型爲VOID,它表示不具有返回值,則必須用關鍵字Sub將其聲明成過程。有的函數具有返回值,則必須用關鍵字Function將其聲明成函數,並且在聲明語句的最後要用AS關鍵字指明函數返回值的類型。

    例如add.DLL在VB中就可以聲明爲:
        Declare Function ADD Lib "c:\add.dll" (ByVal X AS Integer, ByVal Y AS Integer, ByVal filein as string) AS Integer

    通過此聲明語句將函數ADD聲明到VB中,便可直接調用。


動態調用詳解:

    首先調用API LoadLibaray 裝載dll,然後調用API GetProcAddress 得到dll的對應方法的地址。因爲vb不像其他的有函數指針,在vb中聲明函數原形,怎樣把得到的函數地址賦給這個原形有些麻煩。

解決辦法1:

Option Explicit 
 
'我們要調用沒有聲明的API(dll)的功能! 
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long '釋放LoadLibrary載入的動態鏈接庫,非零表示成功,零表示失敗。 
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 '檢索指定的動態鏈接庫(DLL)中的輸出庫函數地址(超找函數入口地址),成功則返回值是DLL中的輸出函數地址,失敗返回值是NULL。 
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long '將消息信息傳送給指定的窗口過程。 
 
Private Sub Form_Load() 
    Dim LibHand As Long '載入的dll句柄 
    LibHand = LoadLibrary("user32")     '將user32載入到內存。 
    CallWindowProc GetProcAddress(LibHand, "SetWindowTextA"), Me.hWnd, CStr(Now), ByVal 0&, ByVal 0& '調用SetWindowTextA函數功能 
    FreeLibrary LibHand '釋放映射庫的地址 
End Sub


解決辦法2:
 
下面是動態調用MessageBoxA的源代碼,上面的步驟被封裝到RunDll32函數中,可放到模塊(CallAPIbyName.bas)中: 
    Dim s1() As Byte, s2()   As Byte 
    Const hWnd = 0 
    Dim ret  As Long 
    s1 = StrConv("Hello~World", vbFromUnicode) 
    s2 = StrConv("VBNote", vbFromUnicode) 
    ret = RunDll32("user32", "MessageBoxA", hWnd, VarPtr(s1(0)), VarPtr(s2(0)), 0&) 
End Sub 
 
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 
    hModule = LoadLibrary(ByVal LibFileName)    '讀取API庫 
    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 
    RunDll32 = CallWindowProc(GetCodeStart(hProc, Params), 0, 1, 2, 3)  '執行Assembly   Code部分 
    FreeLibrary hModule '釋放空間 
End Function

解決辦法3:

在VB中嵌入彙編實現。loadlibary取得DLL,GetProcAddress取得函數地址,用VB嵌入彙編的寫法壓所需參數,CallWindowProc調用GetProcAddress返回的地址。

本文“【VB技巧】VB靜態調用與動態調用dll詳解”,來自:Nuclear'Atk 網絡安全研究中心

發佈了1 篇原創文章 · 獲贊 8 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章