Find the associated EXE file – Updated

I wanted to provided an update to code provided on The Access Web’s website to find the associate executable to a file.  The original article/code can be found at:

 

My goal was to make it 64-bit compliant, but once I started doing so and investigating, I also decided to update the declarations, constants, messages to match those in Microsoft documentation for the API.  The resulting then became:

#If VBA7 Then
    Private Declare PtrSafe Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As LongPtr
#Else
    Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
#End If

Private Const MAX_PATH = 260
Private Const SE_ERR_FNF = 2
Private Const SE_ERR_PNF = 3
Private Const SE_ERR_ACCESSDENIED = 5
Private Const SE_ERR_OOM = 8
Private Const SE_ERR_NOASSOC = 31


'---------------------------------------------------------------------------------------
' Procedure : FindEXE
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve a file's associated execuatble path and file
' Copyright : Original version taken from Dev Ashish and adapted from 64-bit
'             http://theaccessweb.com/api/api0023.htm
' References: https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-findexecutablea
'///////////////////////////////////////////////////////////////////////////////////////
' Comment   : I have found this API to be unreliable, especially with accdb files!
'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFile     : File with extension to find the executable of
' sDirectory: Path where the file is locates (trailing \ is optional)
'
' Usage:
' ~~~~~~
' ? FindEXE("Setup.vbs", "F:\Documents\Clients\Shell\Delivered\")
'   Returns -> C:\WINDOWS\System32\WScript.exe
'
' ? FindEXE("Accounts.xlsm", "C:\Users\Dev\Desktop")
'   Returns -> C:\Program Files (x86)\Microsoft Office\Office15\EXCEL.EXE
'
' ? FindEXE("Package41.zip", "C:\Users\Dev\Desktop")
'   Returns -> C:\WINDOWS\Explorer.exe
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1                                 Original release by Dev Ashish
' 2         2023-09-06              Updated API Declaration per Microsoft documentation
'                                   Made 64-bit compliant/CCD
'                                   Update constants to match official documentation
'                                   Update errors msgs to match official documentation
'---------------------------------------------------------------------------------------
Function FindEXE(sFile As String, _
                 sDirectory As String) As String
    #If VBA7 Then
        Dim lRetVal           As LongPtr
    #Else
        Dim lRetVal           As Long
    #End If
    Dim lpResult              As String

    lpResult = Space(MAX_PATH)
    lRetVal = FindExecutable(sFile, sDirectory, lpResult)

    If lRetVal > 32 Then    'Success
        FindEXE = lpResult
    Else    'We have a problem!
        Select Case lRetVal:
            Case SE_ERR_FNF: FindEXE = "Error: The specified file was not found."
            Case SE_ERR_PNF: FindEXE = "Error: The specified path is invalid."
            Case SE_ERR_ACCESSDENIED: FindEXE = "Error: The specified file cannot be accessed."
            Case SE_ERR_OOM: FindEXE = "Error: The system is out of memory or resources."
            Case SE_ERR_NOASSOC: FindEXE = "Error: There is no association for the specified " & _
                                           "file type with an executable file."
        End Select
    End If
End Function

Usage Example(s)

To retrieve the associated executable for a given file one would simply do:

Debug.Print FindEXE("Accounts.xlsm", "C:\Users\Dev\Desktop\")

which then would return something along the lines of:

C:\Program Files (x86)\Microsoft Office\Office15\EXCEL.EXE

Warning!

IMHO, this is not a very reliable approach to determining the executable. In my testing, on a multitude of VMs, it failed to return an executable for a number of files including, but not limited to: accdb files, png files, bat file returned weird values… so be sure to perform extensive testing before ever trying to implement it into a production environment.