Nothing too exciting here. This is just some code I wrote to demonstrate how to call a function in a DLL through the use of LoadLibrary and GetProcAddress.
I was doing some experiments for this thread and I found it very interesting that it was hard to find a proper or complete VB.Net sample that shows how to use LoadLibrary so I decided to contribute a sample myself.
Here:-
Code:
Imports System.Runtime.InteropServices
Public Class Form1
Private Delegate Function GetWindowRectDelegate(ByVal hWnd As IntPtr, ByRef lpRect As WindowsAPI.RECT) As Boolean
'Define a delegate type for the GetWindowRect function from the User32.Dll library.
Private GetWndRect As GetWindowRectDelegate
'Handle to the User32.Dll loaded into our process's address space by LoadLibrary.
'We need to keep this handle so we can free the library when we are done with it.
Private _hModule As IntPtr
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Loads our DLL into the application's address space
InitLib()
'Obtain a delegate to call User32's GetWindowRect function from .Net. and assign
'it to a delegate type variable. We can then use this variable to call the function.
GetWndRect = GetFunctionFromLibrary(Of GetWindowRectDelegate)(_hModule, "GetWindowRect")
End Sub
Private Sub InitLib()
'Loads User32.Dll into the address space of our application
_hModule = WindowsAPI.LoadLibraryW("User32.dll")
'Checks to make sure the LoadLibrary call succeeded
If _hModule = IntPtr.Zero Then
Throw New Exception($"LoadLibrary failed with error {Marshal.GetLastWin32Error.ToString}")
End If
End Sub
Private Shared Function GetFunctionFromLibrary(Of T)(ByVal hModule As IntPtr, ByVal funcName As String) As T
Dim ptr As IntPtr
'Try to obtain a raw function pointer to the function from the DLL
ptr = WindowsAPI.GetProcAddress(hModule, funcName)
'Make sure it succeeded
If ptr = IntPtr.Zero Then
Throw New Exception($"Failed to obtain address of function '{funcName}'. Error code {Marshal.GetLastWin32Error.ToString}")
End If
'Convert the raw function pointer to a .Net delegate so we can call it
Return Marshal.GetDelegateForFunctionPointer(Of T)(ptr)
End Function
Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
UpdateDisplay()
End Sub
Private Sub Form1_Move(sender As Object, e As EventArgs) Handles Me.Move
UpdateDisplay()
End Sub
Private Sub UpdateDisplay()
Dim r As WindowsAPI.RECT
'Make sure we do have a function to call from the delegate
'variable.
If GetWndRect IsNot Nothing Then
'Call User32's GetWindowRect function through our .Net delegate
GetWndRect(Me.Handle, r)
Me.Text = $"Left = {r.Left.ToString}, Top = {r.Top.ToString}, Right = {r.Right.ToString}, Bottom = {r.Bottom.ToString}"
End If
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
If Not WindowsAPI.FreeLibrary(_hModule) Then
Throw New Exception("FreeLibrary call failed.")
End If
End Sub
End Class
Public Class WindowsAPI
<StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
<DllImport("kernel32.dll")>
Public Shared Function LoadLibraryW(<MarshalAs(UnmanagedType.LPWStr)> ByVal lpLibFileName As String) As IntPtr
End Function
'Notice a very important detail here, which is, we MUST marshal lpProcName as
'an ANSI String. There is no wide version of GetProcAddress for some reason.
<DllImport("kernel32.dll")>
Public Shared Function GetProcAddress(ByVal hModule As IntPtr,
<MarshalAs(UnmanagedType.LPStr)> ByVal lpProcName As String) As IntPtr
End Function
<DllImport("Kernel32.dll")>
Public Shared Function FreeLibrary(ByVal hLibModule As IntPtr) As Boolean
End Function
End Class
Create a new WinForms VB.Net project, double click Form1 and place the above code there. Run the application and move/resize the form. It's title bar should be constant updating with information on the size and location of the Form on the screen. The demo shows how to call the User32 DLL function GetWindowRect using LoadLibrary and GetProcAddress and the data in the title bar is obtained from calling GetWindowRect in this manner.
Have fun.