Windows
does not expose an API that will return the total size of a folder, or the total
size of all specified file types (ie *.doc), so we revert
to the trusty FindFirstFile and FindNextFile APIs to retrieve this info for us.
This demo shows how to retrieve the directory size beginning at the root path,
and optionally recursing and including the size of subdirectories under that
path. By changing the hard-coded *.* you can restrict the returned value to a
specific file type.
As
used in the other search demos, a customized User-Defined Type is used as
the mechanism to pass multiple search parameters to the search routines.
This allows for extending the capabilities of a routine by simply adding
a new member to the UDT and coding for it.
The default mode is to search only within the specified folder. When the
"Recurse" button is checked the specified folder, and all subfolders
under it, are searched. When a drive alone is specified as the
source path, without recursion the files in the root are returned,
otherwise the recursion searches all folders on the drive.
Note:
-
The demo uses a modified TrimNull method that relies on StrPtr
available natively in VB5 and VB6. VB4-32 users will have to declare
this as an API exposed by VB4-32 runtime dll (ie in VB5, the declare is
Declare Function VarPtr Lib "msvbvm50.dll" (var as Any) As Long).
|
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you may not reproduce
' or publish this code on any web site,
' online service, or distribute as source
' on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const vbDot = 46
Private Const MAXDWORD As Long = &HFFFFFFFF
Private Const MAX_PATH As Long = 260
Private Const INVALID_HANDLE_VALUE = -1
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
Private Type FILE_PARAMS
bRecurse As Boolean
nFileCount As Long
nFileSize As Currency '64 bit value
nSearched As Long
sFileNameExt As String
sFileRoot As String
End Type
Private Declare Function FindClose Lib "kernel32" _
(ByVal hFindFile As Long) As Long
Private Declare Function FindFirstFile Lib "kernel32" _
Alias "FindFirstFileA" _
(ByVal lpFileName As String, _
lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" _
Alias "FindNextFileA" _
(ByVal hFindFile As Long, _
lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function lstrlen Lib "kernel32" _
Alias "lstrlenW" (ByVal lpString As Long) As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Sub Form_Load()
Text1.Text = "c:\windows"
Check1.Caption = "Recurse"
Command1.Caption = "GetDirectorySize"
End Sub
Private Sub Command1_Click()
Dim tstart As Single 'timer var for this routine only
Dim tend As Single 'timer var for this routine only
Dim fp As FILE_PARAMS
Text2.Text = ""
Text3.Text = ""
Text4.Text = ""
With fp
.sFileRoot = QualifyPath(Text1.Text) 'start path
.sFileNameExt = "*.*" 'files of interest
.bRecurse = Check1.Value = 1 'True = recurse
End With
tstart = GetTickCount()
Call GetDirectorySize(fp.sFileRoot, fp)
tend = GetTickCount()
Text2.Text = Format$(fp.nSearched, "###,###,###,##0")
Text3.Text = Format$(fp.nFileSize, "###,###,###,##0")
Text4.Text = FormatNumber((tend - tstart) / 1000, 2) & " seconds"
End Sub
Private Sub GetDirectorySize(sRoot As String, fp As FILE_PARAMS)
Dim wfd As WIN32_FIND_DATA
Dim hFile As Long
hFile = FindFirstFile(sRoot & "*.*", wfd)
If hFile <> INVALID_HANDLE_VALUE Then
Do
If Asc(wfd.cFileName) <> vbDot Then
If (wfd.dwFileAttributes And vbDirectory) Then
If fp.bRecurse Then
GetDirectorySize sRoot & TrimNull(wfd.cFileName) & "\", fp
End If 'If fp.bRecurse
Else
fp.nFileCount = fp.nFileCount + 1
fp.nFileSize = fp.nFileSize + _
((wfd.nFileSizeHigh * _
(MAXDWORD + 1)) + _
wfd.nFileSizeLow)
End If 'If WFD.dwFileAttributes
End If 'If Asc(wfd.cFileName)
fp.nSearched = fp.nSearched + 1
Loop While FindNextFile(hFile, wfd)
End If 'If hFile
Call FindClose(hFile)
End Sub
Private Function TrimNull(startstr As String) As String
TrimNull = Left$(startstr, lstrlen(StrPtr(startstr)))
End Function
Private Function QualifyPath(sPath As String) As String
If Right$(sPath, 1) <> "\" Then
QualifyPath = sPath & "\"
Else
QualifyPath = sPath
End If
End Function
|