Re: list all files including full path
Based on timing tests INamespaceWalk is faster than FindFirstFile/FindNextFile, IShellFolder.EnumObjects, and shell32.folder methods (and presumably faster than IEnumShellItems since it's higher level than IShellFolder); Dir() may possibly be faster, and is no doubt easier, but it doesn't support unicode. The other advantage of INamespaceWalk is that results are always in the correct sorted order (natural sort, like Explorer, where a9 comes before a12), so you don't have to sort them yourself like other methods.
It does require Vista or higher though; and some complicated stuff if you need the ability to cancel while in progress.
For XP support, and Unicode support, you can use either of these methods:
Module level variables mCnt As Long, mSrs() As String (file list), and mSpec As String (= "*") to list all files.
Method 1, FindFirstFile/FindNextFile. sRoot is the folder you want listed.
Code:
Private Sub search2(sRoot As String)
Dim WFD As WIN32_FIND_DATAW
Dim hFile As Long
Dim pszPath As String
sRoot = AddBackslash(sRoot)
hFile = FindFirstFileW(StrPtr(sRoot & "*"), WFD)
If hFile <> INVALID_HANDLE_VALUE Then
Do
pszPath = StripNullsW(StrConv(WFD.cFileName, vbFromUnicode))
If (WFD.dwFileAttributes And vbDirectory) Then
If Asc(pszPath) <> vbDot Then
search2 sRoot & pszPath
End If
Else
If PathMatchSpec(StrPtr(pszPath), StrPtr(mSpec)) Then
ReDim Preserve mSrs(mCnt)
mSrs(mCnt) = sRoot & pszPath
mCnt = mCnt + 1
End If
End If
Loop While FindNextFileW(hFile, WFD)
End If
End Sub
Method 2, IShellFolder/IEnumIDList, pidl is the result of ILCreateFromPathW(StrPtr(pathyouwanttolist)
Code:
Private Sub search1(pidl As Long)
Dim pcelt As Long
Dim pidlChild As Long
Dim psf As IShellFolder
Dim pszPath As String
Set psf = GetIShellFolder(isfDesktop, pidl)
Dim ieidl As IEnumIDList
psf.EnumObjects 0, SHCONTF_FOLDERS Or SHCONTF_NONFOLDERS, ieidl
Dim pidlFQC As Long
Do While (ieidl.Next(0, pidlChild, pcelt) = S_OK)
pidlFQC = ILCombine(pidl, pidlChild)
pszPath = GetPathFromPIDLW(pidlFQC)
' Debug.Print pszPath
If PathIsDirectoryW(StrPtr(pszPath)) Then
search1 pidlFQC
Else
If PathMatchSpec(StrPtr(pszPath), StrPtr(mSpec)) Then
ReDim Preserve mSrs(mCnt)
mSrs(mCnt) = pszPath
mCnt = mCnt + 1
End If
End If
ILFree pidlFQC
ILFree pidlChild
Loop
Set ieidl = Nothing
Set psf = Nothing
End Sub
The IShellFolder method (and INamespaceWalk) would require oleexp3.tlb to be added as a reference (but not distributed with your install, only needed in the IDE).
After calling either search1 or search2, mSrs() will contain a list of every file in every subfolder.
--
Supporting APIs and functions for those methods:
Code:
Public Type WIN32_FIND_DATAW
dwFileAttributes As FILE_ATTRIBUTES
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
'cFileName(2 * MAX_PATH - 1) As Byte
cFileName As String * 520
cAlternate As String * 14
End Type
Public Declare Function FindFirstFileW Lib "kernel32" (ByVal lpFileName As Long, _
lpFindFileData As WIN32_FIND_DATAW) As Long ' If the function succeeds, the return value is a search handle used in a subsequent call to FindNextFile or FindClose
Public Declare Function FindNextFileW Lib "kernel32" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATAW) As Long ' Rtns True (non zero) on succes, False on failure
Public Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Public Declare Function PathMatchSpec Lib "shlwapi" Alias "PathMatchSpecW" (ByVal pszFileParam As Long, ByVal pszSpec As Long) As Long
Public Const INVALID_HANDLE_VALUE = -1&
Public Declare Function SHGetDesktopFolder Lib "shell32" (ppshf As IShellFolder) As Long ' Retrieves the IShellFolder interface for the desktop folder.
Public Declare Function ILCombine Lib "shell32" (ByVal pidl1 As Long, ByVal pidl2 As Long) As Long
Public Declare Function ILCreateFromPathW Lib "shell32" (ByVal pwszPath As Long) As Long
Public Declare Function ILFindLastID Lib "shell32" (ByVal pidl As Long) As Long
Public Declare Sub ILFree Lib "shell32" (ByVal pidl As Long)
Public Declare Function PathIsDirectoryW Lib "shlwapi" (ByVal lpszPath As Long) As Boolean
Public Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long
Public Function StripNullsW(sData As String) As String
StripNullsW = Left$(sData, lstrlenW(ByVal StrPtr(sData)))
End Function
Public Function AddBackslash(s As String) As String
If Len(s) > 0 Then
If Right$(s, 1) <> "\" Then
AddBackslash = s & "\"
Else
AddBackslash = s
End If
Else
AddBackslash = "\"
End If
End Function
Public Function GetIShellFolder(isfParent As IShellFolder, pidlRel As Long) As IShellFolder
Dim isf As IShellFolder
On Error GoTo out
Call isfParent.BindToObject(pidlRel, 0, IID_IShellFolder, isf)
out:
If Err Or (isf Is Nothing) Then
Set GetIShellFolder = isfDesktop
Else
Set GetIShellFolder = isf
End If
End Function
Public Function IID_IShellFolder() As UUID
Static iid As UUID
If (iid.Data1 = 0) Then Call DEFINE_OLEGUID(iid, &H214E6, 0, 0)
IID_IShellFolder = iid
End Function
Public Sub DEFINE_UUID(Name As UUID, L As Long, w1 As Integer, w2 As Integer, B0 As Byte, b1 As Byte, b2 As Byte, B3 As Byte, b4 As Byte, b5 As Byte, b6 As Byte, b7 As Byte)
With Name
.Data1 = L
.Data2 = w1
.Data3 = w2
.Data4(0) = B0
.Data4(1) = b1
.Data4(2) = b2
.Data4(3) = B3
.Data4(4) = b4
.Data4(5) = b5
.Data4(6) = b6
.Data4(7) = b7
End With
End Sub
Public Sub DEFINE_OLEGUID(Name As UUID, L As Long, w1 As Integer, w2 As Integer)
DEFINE_UUID Name, L, w1, w2, &HC0, 0, 0, 0, 0, 0, 0, &H46
End Sub
Re: list all files including full path
The most basic sample:
Code:
Sub DirSearch(ByVal StartDir As String)
Dim s As String
Dim currdir As String
Dim dirlist As New Collection
If Right$(StartDir, 1) <> "\" Then StartDir = StartDir & "\"
dirlist.Add StartDir
While dirlist.Count
'remove current directory from directory list
currdir = dirlist.Item(1)
dirlist.Remove 1
'find all files and subdirectories in current, add to list
s = Dir$(currdir, vbDirectory)
While Len(s)
If (s <> ".") And (s <> "..") Then 'get rid of "." and ".."
If GetAttr(currdir & s) = vbDirectory Then 'add the subdirectory
dirlist.Add currdir & s & "\"
Else 'work on the file
Debug.Print currdir & s
End If
End If
s = Dir$
Wend
Wend
End Sub
Source
Quote:
May I ask other samples from our members that is much faster that what I search from pscode. Thanks
It's up to you to test whether this is faster or slower than the current code you have found.
Re: list all files including full path
Quote:
Originally Posted by
codesearcher
I need to list all windows files on a folder including from its sub-folders.
Can you be more specific as to what you mean by "list"? Where is this "list" going to end up? Is it in a ListBox, ListView & TreeView, TextBox, text file, etc.?
Re: list all files including full path
Quote:
Originally Posted by
fafalone
Based on timing tests
INamespaceWalk is faster than FindFirstFile/FindNextFile, ...
That's actually not true - just did some tests here out of interest - and my results were
showing INameSpaceWalk to be about 2.5-3 times slower than FindFirstFileW/FindNextFileW.
Would be nice when you could correct that in your CodeBank-Thread, before this evolves
into "just another myth".
Hint, when doing such comparisons - one shouldn't include expensive GUI-interactions
(as e.g. feeding a ListView or something) into the timing.
Olaf