Check File Path of Lib for DLL Function in VBA

joh07956

New Member
Joined
Aug 2, 2016
Messages
8
I'm working with a model that references a hard coded file path that points to a .dll file. The code line used to declare the function is as follows:

Code:
Private Declare PtrSafe Function export_function 
      Lib "\\network\public\myfolder\MyDLLFile.dll" _
      (ByVal AddressOfStruct As LongPtr) As Long

The issue is that this model is used on a multitude of networks and that the "libname" needs to change for various users. Currently, the model will run even if this .dll file doesn't exist at the location specified. It even produces some semi-normal looking results, which is very dangerous.

Is it possible to return the address of the Lib for this Function "export_function" before the Function actually called/used in the code?

For example something like:

Code:
Dim CheckFilePath as String
CheckFilePath = Environ(export_function)
'If Statement to check if file exists at "libname" location...

If it is not possible to return the directory of the .dll file, is there a better solution I can use to kill the code when someone attempts to run the model w/o the .dll file's path being updated correctly?
 

Excel Facts

How can you turn a range sideways?
Copy the range. Select a blank cell. Right-click, Paste Special, then choose Transpose.
Have you tried using the Dir Function?
Code:
Debug.Print Dir([COLOR=#333333]"\\network\public\myfolder\MyDLLFile.dll"[/COLOR])

Or load the dll @ runtime Using the LoadLibrary API .. If the dll is not there then the return will be a Null handle so exit your code.
 
Upvote 0
What I'm looking for is a fail-safe to prevent the scenario in which a user didn't update the path. In that event the code still runs and the model produces output. Your first suggestion would still leave room for human error if say a person changed the file path in that line of code, but forgot to update the actual file path in the Lib definition of the Function "export_function". Is there no way to check what directory "export_function" is pointing at after it has been declared?

I'm not very familiar with how to properly load DLL files, are you suggesting an alternative to the "P
rivate Declare PtrSafe Function" method of loading the DLL when you mention the LoadLibrary method? If so, can you be more specific on how I might go about that?
 
Upvote 0
I'm not very familiar with how to properly load DLL files, are you suggesting an alternative to the "Private Declare PtrSafe Function" method of loading the DLL when you mention the LoadLibrary method? If so, can you be more specific on how I might go about that?

You can load the dll @ runtime and call the dll function .. This is ideal when you don't know the exact dll filepath or function.

This approach requires more steps .. It goes something like this :


1- GetModuleHandle to get a handle to the dll module.
2- GetModuleFileName to get the excact dll path(location) from the Module.
3- LoadLibrary to load the dll into the current process.
4- GetProcAddress to get the dll Function Address from the Lib handle.
5- CallWindowProc to actually call the dll function.
6- FreeLibrary to unload the dll from the current process.

Here is an example to call the FindWindow API function exported by the "User32" dll on the excel application main window:

Code:
Option Explicit

Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Declare PtrSafe Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As LongPtr, ByVal lpFileName As String, ByVal nSize As Long) As Long
Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
Declare PtrSafe Function FreeLibrary Lib "kernel32" (ByVal hLibModule As LongPtr) As Long
Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpProcName As String) As LongPtr
Declare PtrSafe Function FindExcelWindow Lib "user32" Alias "CallWindowProcA" (ByVal FindWindowAProcAddr As LongPtr, ByVal ClassName As String, ByVal WindowName As String, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

Sub Test()
    Dim sBuffer As String
    Dim DllFilePath As String
    Dim lRet As Long
    Dim hMod As LongPtr
    Dim hLib As LongPtr
    Dim hProcAddrs As LongPtr
    Dim hwnd As LongPtr
    
    
    hMod = GetModuleHandle("user32")
    
    If hMod Then
        sBuffer = Space(256)
        lRet = GetModuleFileName(hMod, sBuffer, Len(sBuffer))
        If lRet Then
            DllFilePath = Left(sBuffer, lRet)
            hLib = LoadLibrary(DllFilePath)
            If hLib Then
                hProcAddrs = GetProcAddress(hLib, "FindWindowA")
                If hProcAddrs Then
                    hwnd = FindExcelWindow(hProcAddrs, vbNullString, Application.Caption, 0, 0)
                    MsgBox hwnd = Application.hwnd [B][COLOR=#008000]'<== returns TRUE[/COLOR][/B]
                End If
                FreeLibrary hLib
            End If
        End If
    End If
End Sub

Notice that in the above example, I used an Alias of the CallWindowProcA API function.. This is because the FindWindow API takes 2 String arguments.

In your case, because your export function takes only one LongPtr argument, you will need to declare the CallWindowProc API as follwos :
Code:
[COLOR=#000000]Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal Msg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr[/COLOR]

and call the export something like this :
Code:
FuncReturn = CLng(CallWindowProc(hProcAddrs, AddressOfStruct, 0, 0, 0))

where hProcAddrs is the LongPtr address of your "export_function" function , AddressOfStruct is its LongPtr argument and FuncReturn is its return Long value.
 
Upvote 0

Forum statistics

Threads
1,223,264
Messages
6,171,081
Members
452,377
Latest member
bradfordsam

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top