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.
