
Date: Nov 22 1999
From: Olivier Philippe
To: ron@oreilly.com
Subject: Free Disk Space Available
Hi,
I want to know how to get the total amount of available free disk
space if my disk has more than a 2-gigabyte capacity.
Thanks a lot for answering.
Sincerely,
Olivier
Hello Olivier,
Visual Basic 6.0 offers a comparatively new and very accessible (and
still comparatively unknown) method for determining the amount of free
space available on a local drive: the FreeSpace property of the Drive object,
which is part of the file system object model included with the
Scripting Runtime library. The following code fragment, for instance,
retrieves the number of free bytes on drive C:
Dim oFS As New FileSystemObject
Dim lngBytes As Long
lngBytes = oFS.Drives("C").FreeSpace
As your question suggests, though, the FreeSpace property has one very
significant limitation: it is unable to report free storage space
in excess of about 2 gigabytes.
The alternative is to use the Win32 API from Visual Basic. However,
GetDiskFreeSpace, the standard Win32 API function for determining free space
on a drive, suffers from the same limitation: it fails to report free storage
space in excess of about 2GB. This is hardly a coincidence: the FreeSpace
property of the Drive object merely wraps a call to the GetDiskFreeSpace
function in Kernel32.dll. Nor is this surprising: until recently, hard drives
with more than 2GB of total space were rare.
Historically, Microsoft has chosen to enhance the Win32 API by adding a variety
of "extended" functions. In some cases, these extended functions simply address
difficulties that developers were having using the original function. For
instance, the Win32 GetVersionEx function is much easier to use than the
original GetVersion function. In other cases, though, the extended function
reflects some technical change in Windows' hardware support or in the design
of the Windows family of operating systems. For example, the RegQueryValue
function retrieves the default value of a registry key, whereas the
RegQueryValueEx function retrieves the named value of an open registry key.
In view of this, it's not surprising that the increasingly obsolete
GetDiskFreeSpace function has been supplemented by a new function named
GetDiskFreeSpaceEx.
The syntax of GetDiskFreeSpaceEx is: (Click here for code example)
Its parameters are: (Click here
for code example)
Like all Win32 prototypes, this prototype assumes that a C or C++ programmer is
calling the function. But what about a VB programmer? The first parameter,
lpDirectoryName, is fairly straightforward; it calls for a pointer to a standard null-terminated C string. This simply requires that we pass our string by value
to the GetDiskFreeSpaceEx function.
The remaining parameters are somewhat problematic. All three parameters are of
type PULARGE_INTEGER, which means that they are pointers to unsigned large
integers. This poses two difficulties for the Visual Basic programmer. First,
large (64-bit) integers are a fairly new data type to the Win32 API that
aren't supported by VB. Second, except for the Byte data type, VB doesn't support unsigned data types.
However, PULARGE_INTEGER is not a native C/C++ data type. Instead, it is defined as
struct {
DWORD LowPart;
DWORD HighPart;
} ;
This means that we can define it in Visual Basic as a user-defined type that
we'll call LargeInt and that consists of two long integers, as follows:
Public Type LargeInt
lngLower As Long
lngUpper As Long
End Type
Note that the lower-order word precedes the high-order word in memory, which seems counter-intuitive. Since we can use the LargeInt structure, that leaves
only the signed/unsigned problem, which we'll have to address in code. So we
can use the following Declare statement in order to call the GetDiskFreeSpaceEx function: (Click here for code
example)
We can then enumerate available drives (or at least the non-removable ones -- this
prevents an error from occurring if the media in non-removable drives are not
present) and calculate their free storage space with a code fragment like the
following, which adds the drive letter and its free space to a list
box: (Click here for code
example)
The only thing that really needs comment here is our handling of the 64-bit
integer user-defined type. The highest-order bit of each of the Longs that
forms a LargeInt variable is a sign bit. The sign bit not only indicates to VB
that a long integer is negative, but it produces a value that is 4,294,967,296
less than the unsigned representation of the same value. (That's because the
highest-order byte is the byte in the 31st position, and 2^31 is 2,147,483,648. That bit is interpreted as being equal to -2,147,483,648 in a signed
representation and 2,147,483,648 in an unsigned one, a difference of
4,294,967,296.) For all practical purposes, we don't need to be concerned with
the sign of the high-order word, since drives now (and probably for all time)
simply aren't that large. Finally, the value of the high-order word is 2^32,
or 4,294,967,296 greater than the low-order word. Because of its greater range, we assign the result of our manipulation of the two members of a LargeInt
variable to a variable of type Double.
The GetDiskFreeSpaceEx function is available on Windows 95 SR2 or later and on
Windows NT 4.0 or later. You can download a
sample program that
illustrates the use of the function and compares the results with the
traditional methods of calculating free disk space.
Thanks for submitting this question. Until it arrived, I had never noticed that
the FreeSpace property and the GetDiskFreeSpace function inaccurately reported
available free space on drives with over 2GB free space.
--Ron
Return to: Ron's Archive

|