DLL(Win32 API など) を実行時に動的ロードする。(LoadLibrary,GetProcAddress,FreeLibrary)
Win32APIを使用する場合はDLLImport属性を付けて使用したいAPIを事前に定義して使います。DllImport属性は使用したいDLLとのリンクがコンパイル時に設定されるためアプリ起動時にリンクを解決しようとします。(リンクを解決するというのは、DLLをメモリ上にロードし使用したい関数のエントリーポイントを決定することです。)これは、DLLとの通常のリンクの仕方ですが、リンクしたいDLLがシステムに存在しない場合や、使用したい関数が対象のDLLに存在しない場合、(OSのバージョンなどの違いで発生することが良くあります。)アプリはリンクに失敗し起動しません。
これに対処するためには、DLLの実行時読み込み(動的読み込みとも言います)を使用します。
実行時読み込みには、LoadLibrary,GetProcAddress,FreeLibraryの各Win32APIを使用します。アプリの起動時ではなく、コードの実行によってDLLとのリンクを解決することができるため、DLLが無い場合やDLLの中に使用したい関数が無い場合などでも、その部分だけ動かさずに処理を続行することができます。また、使用する直前までDLLのロードを遅らせたり、不要になったDLLをアンロードさせたりすることが出来るようになります。
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.ClickDim l As New DynamicLibraryLoader
Dim result As Boolean = l.Load("user32.dll")
If result = True ThenTry
Dim d As [Delegate] = l.GetDelegate("MessageBoxA", GetType(MessageBox))
If Not d Is Nothing ThenDim m As MessageBox = CType(d, MessageBox)
m(IntPtr.Zero, "メッセージボックスのテストです", "こんにちは", 0)End If
Finally
l.Free()End Try
End If
End Sub
DynamicLibraryLoaderクラス
Imports System
Imports System.Runtime.InteropServicesPublic Class DynamicLibraryLoader
_
Private Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function
_
Private Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
End Function
_
Private Shared Function GetProcAddress(ByVal hModule As IntPtr, ByVal lpProcName As String) As IntPtr
End FunctionPrivate _libraryModule As IntPtr = IntPtr.Zero
Private _lastErrorNo As Integer = 0
Private _errorMessage As String = String.EmptyPublic ReadOnly Property LastErrorNo() As Integer
Get
Return _lastErrorNo
End Get
End PropertyPublic ReadOnly Property ErrorMessage() As String
Get
Return _errorMessage
End Get
End PropertyPublic Function Load(ByVal fileName As String) As Boolean
_libraryModule = LoadLibrary(fileName)
If _libraryModule = IntPtr.Zero ThenDim lastError As Integer = Marshal.GetHRForLastWin32Error
Dim ex As Exception = Marshal.GetExceptionForHR(lastError)_lastErrorNo = lastError
_errorMessage = ex.MessageReturn False
End If
Return True
End Function
Public Function GetDelegate(ByVal procName As String, ByVal delegateType As Type) As [Delegate]
If _libraryModule = IntPtr.Zero Then
Return Nothing
End IfDim procPtr As IntPtr = GetProcAddress(_libraryModule, procName)
If procPtr = IntPtr.Zero ThenDim lastError As Integer = Marshal.GetHRForLastWin32Error
Dim ex As Exception = Marshal.GetExceptionForHR(lastError)_lastErrorNo = lastError
_errorMessage = ex.MessageReturn Nothing
End If
Dim d As [Delegate] = Marshal.GetDelegateForFunctionPointer(procPtr, delegateType)
Return dEnd Function
Public Function Free() As Boolean
If _libraryModule <> IntPtr.Zero Then
Dim result As Boolean = FreeLibrary(_libraryModule)
If result = False ThenDim lastError As Integer = Marshal.GetHRForLastWin32Error
Dim ex As Exception = Marshal.GetExceptionForHR(lastError)_lastErrorNo = lastError
_errorMessage = ex.MessageReturn False
End If
End If
Return True
End Function
End Class