如何調用外部DLL內的方法與資源
一般來說調用DLL可以透過參考的方式來達到目的。但在某些情況下,需要臨時參考某個DLL檔時,或是想把DLL包入資源檔中,就可以透過 Reflection 來將程式庫載入。
範例:
引用外部 DLL 檔案,調用方法與資源檔。
動作:
1. 按下按鍵(Button1),從 Utility.DLL 中調用方法 GetNicIPAddrNumber 取回目前電腦所使用的 IP (數值)並填入文字方塊(TEXTBOX1)內。
2. 調用 Utility.DLL 中的資源,將圖示檔(OnLineIcon)取出後,置換目前視窗所使用的圖示。
原始碼:
Dim asmUtility As System.Reflection.Assembly = System.Reflection.Assembly.LoadFile("C:\TEST\Utility.dll")
For Each tmpType As Type In asmUtility.GetTypes
Select Case tmpType.Name
Case "IPTools"
Me.TEXTBOX1.Text = tmpType.InvokeMember(Nothing, Reflection.BindingFlags.DeclaredOnly Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.CreateInstance, Nothing, Nothing, Nothing).GetNicIPAddrNumber
Case "Resources"
Me.Icon = tmpType.InvokeMember("OnLineIcon", Reflection.BindingFlags.GetProperty, Nothing, Nothing, Nothing)
End Select
Next
End Sub
Binding Flags 列舉型別
Default | 指定無繫結旗標。 |
IgnoreCase | 指定繫結時不考慮成員名稱的大小寫。 |
DeclaredOnly | 指定只考慮在所提供型別階層層級宣告的成員。不考慮繼承成員。 |
Instance | 指定執行個體成員將包含在搜尋中。 |
Static | 指定靜態成員將包含在搜尋中。 |
Public | 指定搜尋中要包含公用 (Public) 成員。 |
Non Public | 指定在搜尋中包含非公用成員。 |
FlattenHierarchy | 指定應傳回在階層之上的 Public 成員和受保護的靜態 (Static) 成員。不會傳回繼承類別中的私用靜態成員。靜態成員包括欄位、方法、事件和屬性。巢狀型別 (Nested Type) 不會傳回。 |
InvokeMethod | 指定要叫用方法。這不能是建構函式或型別初始設定式。 |
CreateInstance | 指定反映應該建立指定型別的執行個體。呼叫符合指定引數的建構函式。所提供的成員名稱會忽略。如果沒有指定查詢的類型,則會套用 (Instance | Public)。不可能呼叫型別初始設定式。 |
GetField | 指定所指定欄位的值應傳回。 |
SetField | 指定應設定所指定欄位的值。 |
GetProperty | 指定所指定屬性的值應傳回。 |
SetProperty | 指定應設定所指定屬性的值。對於 COM 屬性來說,指定這個繫結旗標等同於指定 PutDispProperty 和 PutRefDispProperty。 |
PutDispProperty | 指定要叫用 COM 物件上的 PROPPUT 成員。PROPPUT 會指定使用一個值的屬性設定功能。如果屬性同時具有 PROPPUT 和 PROPPUTREF,而且必須區分呼叫哪一個,則使用 PutDispProperty。 |
PutRefDispProperty | 指定應該要叫用 COM 物件上的 PROPPUTREF 成員。PROPPUTREF 會指定要使用參考而非數值的屬性設定函式。如果屬性同時具有 PROPPUT 和 PROPPUTREF,而且必須區分呼叫哪一個,則使用 PutRefDispProperty。 |
ExactBinding | 指定所提供引數型別必須確實符合對應的型式參數型別。如果呼叫端提供非 Null 的 Binder 物件,則反映會擲回例外狀況,因為那表示呼叫端正在提供會選擇適當方法的 BindToXXX 實作。 |
SuppressChangeType | 尚未實作。 |
OptionalParamBinding | 傳回成員集,其參數計數會符合所提供引數的數目。這個繫結旗標用於具有預設值參數的方法和具有變數引數 Varargs 的方法。這個旗標應該只與 Type.InvokeMember 使用。 |
IgnoreReturn | 用於 COM Interop 以指定成員的傳回值可忽略。 |
UTILITY.DLL 原始碼
''' <summary>
''' 取回網路卡 IP 位址(數值模式)
''' </summary>
''' <param name="intIndex">編號。預設為第一組 IP 位址</param>
Public Shared Function GetNicIPAddrNumber(Optional ByVal intIndex As Integer = 0) As Long
Dim strAddr As String = GetNicIPAddr(intIndex)
Return IP2DEC(strAddr)
End Function
''' <summary>
''' 取回網路卡 IP 位址
''' </summary>
''' <param name="intIndex">編號。預設為第一組 IP 位址</param>
Public Shared Function GetNicIPAddr(Optional ByVal intIndex As Integer = -1) As String
Dim strHostName As String = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties.HostName
Dim tmpString As String = ""
If intIndex > -1 Then
tmpString = System.Net.Dns.GetHostEntry(strHostName).AddressList(intIndex).ToString
Else
For Each tmpIPaddr As Net.IPAddress In System.Net.Dns.GetHostEntry(strHostName).AddressList
If Not tmpIPaddr.IsIPv6LinkLocal Then
tmpString = tmpIPaddr.ToString
Exit For
End If
Next
End If
If tmpString.Trim = "" Then
Return ""
Else
Return CInt(tmpString.Split(".")(0)).ToString("000") & "." & CInt(tmpString.Split(".")(1)).ToString("000") & "." & CInt(tmpString.Split(".")(2)).ToString("000") & "." & CInt(tmpString.Split(".")(3)).ToString("000")
End If
End Function
''' <summary>
''' 將 IP 位址 (nnn.nnn.nnn.nnn) 轉換為 IP 數值
''' </summary>
''' <param name="IPAddress">文字格式的 IP 位址</param>
''' <returns>數值型態的 IP 位址</returns>
Public Shared Function IP2DEC(ByVal IPAddress As String) As Long
Dim strIPs() As String
Dim lngReturn As Long = 0
strIPs = Split(IPAddress, ".")
If UBound(strIPs) <> 3 Then Return 0
For i As Integer = 0 To UBound(strIPs)
If (CLng(strIPs(i)) < 0) Or (CLng(strIPs(i)) > 255) Then Return 0
Next
lngReturn = (CLng(strIPs(0)) * (256 ^ 3)) + (CLng(strIPs(1)) * (256 ^ 2)) + (CLng(strIPs(2)) * 256) + (CLng(strIPs(3)))
Return lngReturn
End Function
End Class
參考 COM 元件範例:
使用 Windows Media Player 的 COM 元件Interop.WMPLib.dll,將此元件加入到資源檔中,再來透過資源檔來調用其功能。
Dim objWMP as Object
asmWMP = System.Reflection.Assembly.Load(My.Resources.Interop_WMPLib)
objWMP = System.Activator.CreateInstance(asmWMP.GetType("WMPLib.WindowsMediaPlayerClass"))
播放檔案
objWMP.URL = “要播放的檔案”
objWMP.settings.autoStart = False
objWMP.settings.playCount = 1
objWMP.controls.play()
停止播放
objWMP.controls.stop()
看吧,一切就是這麼簡單。
程式是運氣與直覺堆砌而成的奇蹟。
若不具備這兩者,不可能以這樣的工時實現這樣的規格。
修改規格是對奇蹟吐槽的褻瀆行為。
而追加修改則是相信奇蹟還會重現的魯莽行動。