File not found when loading dll from vb6

I declare and call the dll function using the following syntax in VB6:

'Declare the function Private Declare Sub MYFUNC Lib "mylib.dll" () 'Call the function MYFUNC 

A function call results in a File not found: mylib.dll . This happens when the application is launched from the vb6 IDE or from a compiled executable.

The dll is in the working directory, and I checked that it was found using ProcMon.exe from sysinternals. There are no unsuccessful loads, but the Intel Fortran DLL does not load (before this, the ProcMon trace stops).

I also tried to run the application in WinDbg.exe, and, oddly enough, it works! There are no failures on this line. The ProcMon trace shows that the Intel Fortran DLL loads when the program starts in this way.

The DLL is compiled using Fortran Composer XE 2011.

Can anybody help?

+4
source share
5 answers

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 
+5
source

The .dll must be in the current "working" directory (or registered), otherwise at run time the application will not be able to find it.

make:

MsgBox "Current Directory" and "CurDir

And then compare this to what you expected. The .dll file must be in this directory.

+3
source

My standard first approach to this problem is to bring out ProcMon (or FileMon on XP). Set filters so you can see exactly where he is looking for the file. Perhaps he is looking for the file elsewhere or for a different file name.

+1
source

I tried @roomaroo's answer and he did not give me enough detailed information. Using Dependency Walker helped me solve the problem. Also had to chdir, according to @bnadolson

0
source

Private Sub Ads MYFUNC Lib "mylib.dll" ()

First, you declare a Sub, not a function. They have no return values:

 (vb6) Sub() == (vc++) void Sub() (vb6) Func() as string == (vc++) string Func() 

The path you declared is local to your work environment. Thus, when starting, debug mode is executed using VB6.exe, you need to have mylib.dll in the same directory as VB6.exe.

When you use a private declaration, you may need to consider a wrapper class for your dll. This allows you to group dll sharing together, but allows reuse. Then the class methods are used to access the public function.

So you can use all the above code, copy it to the class

MyClass Code:

 Option Explicit 'Private Declare Sub MYFUNC Lib "mylib.dll" () '<all code above Main()> Private Sub Class_Initialize() 'initialise objects End Sub Private Sub Class_Terminate() 'Set anyObj = Nothing End Sub Public Sub ClassMethod() On Error Goto errClassMethod 'Perhaps look at refactoring the use of msgbox '<code body from Main() given above> exit sub errClassMethod: 'handle any errors End Sub '<all code below main> 

The carving model of the apartment loads ALL modules when the application starts. Using the class will “load” the dll when instantiating the class. In addition, a neater call code is obtained without surrounding obfuscation of Windows API calls: (i.e. ModMain):

 Sub Main() Dim m_base As MyClass Set m_base = New MyClass MyClass.ClassMethod() End Sub 
0
source

All Articles