When loading a DLL, “file not found” can often be misleading. This may mean that the DLL or the file on which it depends is missing, but if that were the case, you would notice a problem with Process Monitor.
Often the message “file not found” actually means that the DLL was found, but an error occurred while loading or calling the method.
There are actually three ways to call a procedure in a DLL:
- Locate and load the DLL by running the DllMain method, if any.
- Find the procedure in the DLL.
- Call the procedure.
Errors can occur at any of these stages. VB6 does all this behind the scenes, so you cannot determine where the error occurs. However, you can control the process using the Windows API functions. This should tell you where the error occurs. You can use breakpoints and use Process Monitor to examine the behavior of your program at each point, which can give you more information.
The code below shows how you can call a DLL procedure using the Windows API. To run it, put the code in the new module and set the launch object for your project to "Sub Main".
Option Explicit ' Windows API method declarations Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long 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 Any, ByVal wParam As Any, ByVal lParam As Any) _ As Long Private Declare Function FormatMessage Lib "kernel32" Alias _ "FormatMessageA" (ByVal dwFlags As Long, lpSource As Long, _ ByVal dwMessageId As Long, ByVal dwLanguageId As Long, _ ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Any) _ As Long Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000 Const MyFunc As String = "MYFUNC" Const MyDll As String = "mylib.dll" Sub Main() ' Locate and load the DLL. This will run the DllMain method, if present Dim dllHandle As Long dllHandle = LoadLibrary(MyDll) If dllHandle = 0 Then MsgBox "Error loading DLL" & vbCrLf & ErrorText(Err.LastDllError) Exit Sub End If ' Find the procedure you want to call Dim procAddress As Long procAddress = GetProcAddress(dllHandle, MyFunc) If procAddress = 0 Then MsgBox "Error getting procedure address" & vbCrLf & ErrorText(Err.LastDllError) Exit Sub End If ' Finally, call the procedure CallWindowProc procAddress, 0&, "Dummy message", ByVal 0&, ByVal 0& End Sub ' Gets the error message for a Windows error code Private Function ErrorText(errorCode As Long) As String Dim errorMessage As String Dim result As Long errorMessage = Space$(256) result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, errorCode, 0&, errorMessage, Len(errorMessage), 0&) If result > 0 Then ErrorText = Left$(errorMessage, result) Else ErrorText = "Unknown error" End If End Function