File not found when loading dll from vb6

前端 未结 5 1894
无人共我
无人共我 2020-12-19 08:06

I am declaring and calling a dll function using the following syntax in VB6:

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

\'Call t         


        
相关标签:
5条回答
  • 2020-12-19 08:39

    The .dll must be in the current "working" directory (or registered), otherwise at run-time the application can't find it.

    Do:

    MsgBox "The current directory is " & CurDir

    And then compare that with what you were expecting. The .dll would need to be in that directory.

    0 讨论(0)
  • 2020-12-19 08:41

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

    Firstly you are declaring a Sub, not a function. These don't have return values:

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

    The path you have declared is local to the running environment. Thus when running is debug mode using VB6.exe, you'll need to have mylib.dll in the same directory as VB6.exe.

    As you are using private declare, you might want to consider a wrapper class for your dll. This allows you to group common dll access together but allowing for reuse. Then methods of the class are used to access the exposed function.

    So you can use all the code provided above, copy it into a 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>
    

    Apartment threading model loads ALL modules when the application is started. Using a class will only "load" the dll when the class is instantiated. Also results in neater calling code without the surrounding obfuscation of windows API calls: (ie. modMain):

    Sub Main()
        Dim m_base As MyClass
        Set m_base = New MyClass
        MyClass.ClassMethod()
    End Sub
    
    0 讨论(0)
  • 2020-12-19 08:42

    When loading DLLs, "file not found" can often be misleading. It may mean that the DLL or a file it depends on is missing - but if that was the case you would have spotted the problem with Process Monitor.

    Often, the "file not found" message actually means that the DLL was found, but an error occured when loading it or calling the method.

    There are actually three steps to calling a procedure in a DLL:

    1. Locate and load the DLL, running the DllMain method if present.
    2. Locate the procedure in the DLL.
    3. Call the procedure.

    Errors can happen at any of these stages. VB6 does all this behind the scenes so you can't tell where the error is happening. However, you can take control of the process using Windows API functions. This should tell you where the error is happening. You can alse set breakpoints and use Process Monitor to examine your program's behaviour at each point which may give you more insights.

    The code below shows how you can call a DLL procedure using the Windows API. To run it, put the code into a new module, and set the startup 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
    
    0 讨论(0)
  • 2020-12-19 08:42

    My standard first go-to approach to this issue is to break out ProcMon (or FileMon on XP). Setup the filters so that you can see where exactly it's searching for the file. It is possible that it's looking for the file elsewhere or for a different file name.

    0 讨论(0)
  • 2020-12-19 08:55

    I tried @roomaroo's answer and it didn't give me specific enough info. Using Dependency Walker helped me resolve it. Also had to chdir, as per @bnadolson

    0 讨论(0)
提交回复
热议问题