Get the list of all open file in vba

mehidy1437

Active Member
Joined
Nov 15, 2019
Messages
348
Office Version
  1. 365
  2. 2016
  3. 2013
Platform
  1. Windows
  2. Mobile
  3. Web
Hi guys,

How to get the list of all open file in excel using VBA? Which are currently open.
Open file can be any file, it can be image, dox, pdf, xlsx, ai etc.
 

Excel Facts

Wildcard in VLOOKUP
Use =VLOOKUP("Apple*" to find apple, Apple, or applesauce
Hi mehidy1437

Retrieving the document files that are currently opened in the local machine turned out to be far more difficult than I initially thought but the following code worked for me (albeit a bit slow when scanning for numerous file extensions) ... Hopefully it will work for you as well.

In the follwing sample, I made use of a userform as a user interface for easier use.

Workbook Sample


1- API code in a Standard Module:
VBA Code:
Option Explicit
     
Private Type SYSTEM_HANDLE
    UniqueProcessId As Integer
    CreatorBackTraceIndex As Integer
    ObjectTypeIndex As Byte
    HandleAttributes As Byte
    HandleValue As Integer
    #If VBA7 Then
        pObject As LongPtr
    #Else
        pObject As Long
    #End If
    GrantedAccess As Long
End Type

Private Type SYSTEM_HANDLE_INFORMATION
    uCount As Long
    aSH() As SYSTEM_HANDLE
End Type

Private Type OBJECT_ATTRIBUTES
    #If VBA7 Then
        Length As Long
        RootDirectory As LongPtr
        ObjectName As LongPtr
        Attributes As LongPtr
        SecurityDescriptor As LongPtr
        SecurityQualityOfService As LongPtr
    #Else
        Length As Long
        RootDirectory As Long
        ObjectName As Long
        Attributes As Long
        SecurityDescriptor As Long
        SecurityQualityOfService As Long
    #End If
End Type

Private Type CLIENT_ID
    #If VBA7 Then
        UniqueProcess As LongPtr
        UniqueThread  As LongPtr
    #Else
        UniqueProcess As Long
        UniqueThread  As Long
    #End If
End Type

Private Type UNICODE_STRING
    uLength As Integer
    uMaximumLength As Integer
    pBuffer(3) As Byte
End Type

Private Type SYSTEM_HANDLE_TABLE_ENTRY_INFO
    UniqueProcessId As Integer
    CreatorBackTraceIndex As Integer
    ObjectTypeIndex As Byte
    HandleAttributes As Byte
    HandleValue As Integer
    #If VBA7 Then
        pObject As LongPtr
        GrantedAccess As LongPtr
    #Else
        pObject As Long
        GrantedAccess As Long
    #End If
End Type

#If VBA7 Then

    Private Declare PtrSafe Function AssocQueryStringA Lib "shlwapi.dll" ( _
            ByRef lFlags As Long, _
            ByVal str As Long, _
            ByVal pszAssoc As String, _
            ByVal pszExtra As String, _
            ByVal pszOut As String, _
            ByRef pcchOut As Long) As Long
 
    Private Declare PtrSafe Function NtQuerySystemInformation Lib "NTDLL.DLL" ( _
            ByVal SystemInformationClass As LongPtr, _
            ByVal pSystemInformation As LongPtr, _
            ByVal SystemInformationLength As Long, _
            ByRef ReturnLength As Long) As Long
 
    Private Declare PtrSafe Function GetFinalPathNameByHandleA Lib "kernel32" ( _
            ByVal HANDLE As LongPtr, _
            ByVal lpszFilePath As String, _
            ByVal cchFilePath As Long, _
            ByVal dwFla As Long) As Long
 
    Private Declare PtrSafe Function NtOpenProcess Lib "NTDLL.DLL" ( _
            ByRef ProcessHandle As LongPtr, _
            ByVal AccessMask As Long, _
            ByRef ObjectAttributes As OBJECT_ATTRIBUTES, _
            ByRef ClientId As CLIENT_ID) As Long
 
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
            Destination As Any, _
            Source As Any, _
            ByVal Length As LongPtr)
 
    Private Declare PtrSafe Function NtDuplicateObject Lib "NTDLL.DLL" ( _
            ByVal SourceProcessHandle As LongPtr, _
            ByVal SourceHandle As LongPtr, _
            ByVal TargetProcessHandle As LongPtr, _
            ByRef TargetHandle As LongPtr, _
            ByVal DesiredAccess As Long, _
            ByVal HandleAttributes As Long, _
            ByVal Options As Long) As Long
 
    Private Declare PtrSafe Function NtClose Lib "NTDLL.DLL" ( _
            ByVal ObjectHandle As LongPtr) As Long
         
    Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" ( _
            ByVal lpModuleName As String) As LongPtr
         
    Private Declare PtrSafe Function GetProcAddress Lib "kernel32" ( _
            ByVal hModule As LongPtr, _
            ByVal lpProcName As String) As LongPtr
         
    Private Declare PtrSafe Function FreeLibrary Lib "kernel32" ( _
            ByVal hLibModule As LongPtr) As Long
         
    Private Declare PtrSafe Function GetCurrentProcess Lib "kernel32" ( _
            ) As LongPtr
         
    Private Declare PtrSafe Function CreateRemoteThread Lib "kernel32" ( _
            ByVal hProcess As LongPtr, _
            lpThreadAttributes As Any, _
            ByVal dwStackSize As LongPtr, _
            lpStartAddress As LongPtr, _
            lpParameter As Any, _
            ByVal dwCreationFlags As Long, _
            lpThreadId As Long) As LongPtr
         
    Private Declare PtrSafe Function WaitForSingleObject Lib "kernel32" ( _
            ByVal hHandle As LongPtr, _
            ByVal dwMilliseconds As Long) As Long
 
    Private Declare PtrSafe Function GetExitCodeThread Lib "kernel32" ( _
            ByVal hThread As LongPtr, _
            lpExitCode As Long) As Long
 
    Private Declare PtrSafe Function TerminateThread Lib "kernel32" ( _
            ByVal hThread As LongPtr, _
            ByVal dwExitCode As Long) As Long

#Else

    Private Declare Function AssocQueryStringA Lib "shlwapi.dll" ( _
            ByRef lFlags As Long, _
            ByVal str As Long, _
            ByVal pszAssoc As String, _
            ByVal pszExtra As String, _
            ByVal pszOut As String, _
            ByRef pcchOut As Long) As Long
 
    Private Declare Function NtQuerySystemInformation Lib "NTDLL.DLL" ( _
            ByVal SystemInformationClass As Long, _
            ByVal pSystemInformation As Long, _
            ByVal SystemInformationLength As Long, _
            ByRef ReturnLength As Long) As Long
 
    Private Declare Function GetFinalPathNameByHandleA Lib "kernel32" ( _
            ByVal HANDLE As Long, _
            ByVal lpszFilePath As String, _
            ByVal cchFilePath As Long, _
            ByVal dwFla As Long) As Long
 
    Private Declare Function NtOpenProcess Lib "NTDLL.DLL" ( _
            ByRef ProcessHandle As Long, _
            ByVal AccessMask As Long, _
            ByRef ObjectAttributes As OBJECT_ATTRIBUTES, _
            ByRef ClientId As CLIENT_ID) As Long
 
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
            Destination As Any, _
            Source As Any, _
            ByVal Length As Long)
 
    Private Declare Function NtDuplicateObject Lib "NTDLL.DLL" ( _
            ByVal SourceProcessHandle As Long, _
            ByVal SourceHandle As Long, _
            ByVal TargetProcessHandle As Long, _
            ByRef TargetHandle As Long, _
            ByVal DesiredAccess As Long, _
            ByVal HandleAttributes As Long, _
            ByVal Options As Long) As Long
 
    Private Declare Function NtClose Lib "NTDLL.DLL" ( _
            ByVal ObjectHandle As Long) As Long
         
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" ( _
            ByVal lpModuleName As String) As Long
         
    Private Declare Function GetProcAddress Lib "kernel32" ( _
            ByVal hModule As Long, _
            ByVal lpProcName As String) As Long
         
    Private Declare Function FreeLibrary Lib "kernel32" ( _
            ByVal hLibModule As Long) As Long
         
    Private Declare Function GetCurrentProcess Lib "kernel32" ( _
            ) As Long
         
    Private Declare Function CreateRemoteThread Lib "kernel32" ( _
            ByVal hProcess As Long, _
            lpThreadAttributes As Any, _
            ByVal dwStackSize As Long, _
            lpStartAddress As Long, _
            lpParameter As Any, _
            ByVal dwCreationFlags As Long, _
            lpThreadId As Long) As Long
         
    Private Declare Function WaitForSingleObject Lib "kernel32" ( _
            ByVal hHandle As Long, _
            ByVal dwMilliseconds As Long) As Long
 
    Private Declare Function GetExitCodeThread Lib "kernel32" ( _
            ByVal hThread As Long, _
            lpExitCode As Long) As Long
 
    Private Declare Function TerminateThread Lib "kernel32" ( _
            ByVal hThread As Long, _
            ByVal dwExitCode As Long) As Long

#End If

Private Const ASSOCF_INIT_DEFAULTTOFOLDER = &H8
Private Const ASSOCF_NOTRUNCATE = &H20
Private Const ASSOCF_VERIFY = &H40
Private Const ASSOCSTR_EXECUTABLE = &H2
Private Const STATUS_INFO_LENGTH_MISMATCH = &HC0000004
Private Const SystemHandleInformation = 16&
Private Const DUPLICATE_SAME_ACCESS = &H2
Private Const PROCESS_DUP_HANDLE = (&H40)
Private Const OBJ_INHERIT = &H2
Private Const S_OK As Long = &H0
Private Const E_POINTER As Long = &H80004003
Private Const MAX_PATH = 260
             
#If Win64 Then
    Private Const LONG_SIZE = 8
#Else
    Private Const LONG_SIZE = 4
#End If



Public Function FindFileHandles(ByVal dwProcessId As Long, ByVal ar As Variant) As Collection

    #If VBA7 Then
        Dim hProcessToDup As LongPtr, hFileHandle As LongPtr
    #Else
        Dim hProcessToDup As Long, hFileHandle As Long
    #End If

    Dim oCID As CLIENT_ID
    Dim oOA As OBJECT_ATTRIBUTES
    Dim oInfo As SYSTEM_HANDLE_INFORMATION
    Dim lHandles As Long, lSize As Long, lStatus As Long, I As Long
    Dim sBuffer As String * MAX_PATH, lRet As Long
    Dim bBuffer() As Byte
    Dim sTempArray() As String, sTempString As String
    Dim oTempCollection As New Collection

 
    oOA.Length = Len(oOA)
    oOA.Attributes = oOA.Attributes Or OBJ_INHERIT
    oCID.UniqueProcess = dwProcessId
    lStatus = 0
    lSize = 1
    Do
        ReDim bBuffer(lSize)
        lStatus = NtQuerySystemInformation(SystemHandleInformation, VarPtr(bBuffer(0)), lSize, 0&)
        If (Not NT_SUCCESS(lStatus)) Then
            If (lStatus <> STATUS_INFO_LENGTH_MISMATCH) Then
                Erase bBuffer
                Exit Function
            End If
        Else
            Exit Do
        End If
        lSize = lSize * 2
        ReDim bBuffer(lSize)
    Loop
 
    lHandles = 0
    CopyMemory oInfo.uCount, bBuffer(0), LONG_SIZE
    lHandles = oInfo.uCount
    ReDim oInfo.aSH(lHandles - 1)
    Call CopyMemory(oInfo.aSH(0), bBuffer(LONG_SIZE), Len(oInfo.aSH(0)) * lHandles)
 
    For I = 0 To lHandles - 1
        lStatus = NtOpenProcess(hProcessToDup, PROCESS_DUP_HANDLE, oOA, oCID)
        If hProcessToDup <> 0 Then
            lStatus = NtDuplicateObject(hProcessToDup, oInfo.aSH(I).HandleValue, _
            GetCurrentProcess, hFileHandle, 0, 0, DUPLICATE_SAME_ACCESS)
            If (NT_SUCCESS(lStatus)) Then
                lStatus = MyGetFileType(hFileHandle)
                If lStatus Then
                    lRet = GetFinalPathNameByHandleA(hFileHandle, sBuffer, MAX_PATH, 0&)
                    If lRet Then
                        sTempString = Left(sBuffer, lRet)
                        sTempArray = Split(sTempString, ".")
                        sTempString = sTempArray(UBound(sTempArray))
                        If Application.IfError(Application.Match(sTempString, ar, 0), 0) Then
                            On Error Resume Next
                            oTempCollection.Add Mid(Left(sBuffer, lRet), 5) & _
                            "|" & ExeFromFileExtension(Mid(Left(sBuffer, lRet), 5), ASSOCSTR_EXECUTABLE) _
                            & "|" & dwProcessId, Left(sBuffer, lRet)
                        End If
                    End If
                End If
            End If
        End If
        Call NtClose(hProcessToDup)
        NtClose hFileHandle
        DoEvents
    Next I
 
    Set FindFileHandles = oTempCollection

End Function


Public Function ExeFromFileExtension(ByVal Extension As String, ByVal NameType As Long) As String

    Dim sExtra      As String
    Dim sOutFile    As String
    Dim lFlags      As Long
    Dim lLenOutFile As Long
    Dim lRes        As Long
 
    sOutFile = Space$(MAX_PATH)
    sExtra = vbNullString '"OPEN"
    lLenOutFile = Len(sOutFile)
 
    lRes = AssocQueryStringA(lFlags:=ASSOCF_INIT_DEFAULTTOFOLDER + _
    ASSOCF_NOTRUNCATE + ASSOCF_VERIFY, _
    str:=NameType, _
    pszAssoc:=Extension, _
    pszExtra:=sExtra, _
    pszOut:=sOutFile, _
    pcchOut:=lLenOutFile)
 
    Select Case lRes
        Case S_OK
            ExeFromFileExtension = Left(sOutFile, lLenOutFile - 1)
        Case E_POINTER
            Debug.Print "E_POINTER: sOutFile buffer too small. Bytes Required: " & CStr(lLenOutFile)
        Case Else
            Debug.Print "Other Error: " & CStr(lRes) & " Hex: " & Hex(lRes) & " Ext: " & Extension
    End Select


End Function


#If VBA7 Then
    Private Function MyGetFileType(ByVal hFile As LongPtr) As Long
        Dim hRemProcess     As LongPtr
        Dim hThread         As LongPtr
        Dim pfnThreadRtn    As LongPtr
        Dim hKernel         As LongPtr
#Else
    Private Function MyGetFileType(ByVal hFile As Long) As Long
        Dim hRemProcess     As Long
        Dim hThread         As Long
        Dim pfnThreadRtn    As Long
        Dim hKernel         As Long
#End If

    Dim dwEax         As Long
    Dim dwTimeOut     As Long
    Dim lResult       As Long

    hRemProcess = GetCurrentProcess
    hKernel = GetModuleHandle("kernel32")
    If hKernel = 0 Then
        MyGetFileType = 0
        Exit Function
    End If
    pfnThreadRtn = GetProcAddress(hKernel, "GetFileType")
    If pfnThreadRtn = 0 Then
        FreeLibrary hKernel
        MyGetFileType = 0
        Exit Function
    End If
    hThread = CreateRemoteThread(hRemProcess, ByVal 0&, 0&, ByVal pfnThreadRtn, ByVal hFile, 0, ByVal 0&)
    dwEax = WaitForSingleObject(hThread, 50)
    If dwEax = &H102 Then
        Call GetExitCodeThread(hThread, dwTimeOut)
        Call TerminateThread(hThread, dwTimeOut)
        NtClose hThread
        MyGetFileType = 0
        Exit Function
    End If
    If hThread = 0 Then
        FreeLibrary hKernel
        MyGetFileType = False
        Exit Function
    End If
    GetExitCodeThread hThread, lResult
    MyGetFileType = lResult
    NtClose hThread
    NtClose hRemProcess
    FreeLibrary hKernel
End Function

Private Function NT_SUCCESS(ByVal nStatus As Long) As Boolean
    NT_SUCCESS = (nStatus >= 0)
End Function



2- Code in the UserForm Module:
Code:
Option Explicit

'Add/Remove file extensions to/from the Const as required.
Private Const FILE_EXTENSIONS = "xls-xlsm-xla-xlsx-docm-docx-mp4-mp3-wmv-PPT-PDF-wav-vbs-txt-avi"

Private bSearching As Boolean
Private vArFileExtensions As Variant


Private Sub UserForm_Initialize()

    vArFileExtensions = Split(FILE_EXTENSIONS, "-")
    Me.LbExts.list = vArFileExtensions

    Me.lblFoundFiles.Caption = "Total Files Found : "
    Me.lblTime.Caption = "Time Elapsed :"
    Me.BtnAbort.Enabled = False
 
    bSearching = False

End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If bSearching Then bSearching = False: End
End Sub

Private Sub BtnSearch_Click()
    Me.lblWait.Caption = ""
    Me.lblFoundFiles.Caption = "Total Files Found : "
    Me.lblTime.Caption = "Time Elapsed :"
    If Not bSearching Then BtnSearch.Enabled = False: Call StartSearch
End Sub

Private Sub btnAbort_Click()
    If bSearching Then bSearching = False: End
End Sub


Private Sub StartSearch()

    Dim oOpenFilesCol As New Collection, sTempArray() As String
    Dim I As Long, j As Long, lRow As Long
 
    Me.BtnAbort.Enabled = True
 
    With Sheet1
        .Range("A1:C1").Offset(1).Resize(.Rows.Count - 1, .Columns.Count).ClearContents
        Set oOpenFilesCol = GetOpenFiles(vArFileExtensions)
        lRow = 1
        For I = 1 To oOpenFilesCol.Count
            For j = 1 To oOpenFilesCol.Item(I).Count
                lRow = lRow + 1
                sTempArray = (Split(oOpenFilesCol.Item(I).Item(j), "|"))
                .Cells(lRow, 1) = sTempArray(0): .Cells(lRow, 2) = sTempArray(1): .Cells(lRow, 3) = sTempArray(2)
            Next j
        Next I
        .Columns("A:C").EntireColumn.AutoFit
    End With
 
    BtnSearch.Enabled = True
    Me.BtnAbort.Enabled = False
    Me.lblWait.Caption = ""
    If bSearching Then bSearching = False
    MsgBox "Done."

End Sub

Private Function GetOpenFiles(ByVal vArFileExtensions As Variant) As Collection

    Dim sngStartTime As Single
    Dim lFoundFilesCount As Long, I As Long
    Dim oWMI As Object, oProcList As Object, oProcess As Object
    Dim oOpenFilesCol As New Collection, vArExeNames() As Variant
    Dim sFileExtenstion As String
 
    sngStartTime = Timer
    bSearching = True
    Me.lblWait.Caption = "Search In Progress  - Please Wait ..."
 
    If UBound(vArFileExtensions) <> -1 Then
 
        ReDim vArExeNames(UBound(vArFileExtensions))
     
        For I = 0 To UBound(vArFileExtensions)
            sFileExtenstion = IIf(Left(vArFileExtensions(I), 1) = ".", vArFileExtensions(I), "." & vArFileExtensions(I))
            sFileExtenstion = ExeFromFileExtension(sFileExtenstion, &H2)
            If Len(sFileExtenstion) Then
                vArExeNames(I) = Split(sFileExtenstion, "\")(UBound(Split(sFileExtenstion, "\")))
            End If
        Next I
     
        Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
        Set oProcList = oWMI.ExecQuery("Select * from Win32_Process")
 
        If Len(Join(vArExeNames, "")) Then
            For Each oProcess In oProcList
                If Application.IfError(Application.Match(oProcess.Name, vArExeNames, 0), 0) Then
                    Call oOpenFilesCol.Add(FindFileHandles(oProcess.ProcessID, vArFileExtensions))
                    If oOpenFilesCol.Count Then
                        If Not oOpenFilesCol.Item(oOpenFilesCol.Count) Is Nothing Then
                            lFoundFilesCount = lFoundFilesCount + oOpenFilesCol.Item(oOpenFilesCol.Count).Count
                            Me.lblFoundFiles.Caption = "Found Files : [" & lFoundFilesCount & "]"
                            Me.lblTime.Caption = "Time Elapsed : " & Format(Timer - sngStartTime, "00.00") & " (Secs)"
                            Me.Repaint
                        End If
                    End If
                End If
            Next oProcess
        End If
     
    End If

    Set GetOpenFiles = oOpenFilesCol

End Function
 
Upvote 0
Actually it taking much time.
And details is not coming in excel file.
 
Upvote 0
I was looking for pdf

I tested the code I provided in 3 different machines each running on different OS 32bit and 64bit and in different excel versions xl 2007,2010 and 2016 and they all worked and returned the desired opened files as advertised .... Also, I applied the code to various file extensions such as PDF-XLS-XLSM-DOCX-DOCM-MP4-,WMV and so on.

I did however mention in my post that the search may take a while depending on how many extensions are being searched for... This is expected as the code scans all running processes associared with the provided file extensions.

So, I am not sure why you are having issues.
 
Upvote 0
Its give me the details. after some times.
Its slow may be for my machine.

Many thanks for your kind help.
 
Upvote 0

Forum statistics

Threads
1,215,219
Messages
6,123,690
Members
449,117
Latest member
Aaagu

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