In our C# applications we occasionally use computer drive information. We might for instance want to see how much free disk space there is or don"t have our app download essential files to a removable drive. So how do we access and query computer drives with C#?
IN THIS ARTICLE:
Computer drive information is a useful feature to have in a program. We can use it to notify the user about insufficient disk space. Or prevent that our program stores files on a removable drive that may not be present the next time it runs.
We get drive information in C# with the DriveInfo class (Asad & Ali, 2017; Stephens, 2014). This class is located inside the System.IO namespace – so we typically add using System.IO; at the top of our code when we work with this class. DriveInfo has been available since .NET Framework 2.0 and .NET Core 1.0 (Microsoft Docs, n.d. a, MSDN, n.d. a).
A single DriveInfo object represents one computer drive (Stephens, 2014). We use the object"s properties to get information from that particular drive. This way we look up its drive type, total size in bytes, drive name, root directory, and amount of free space. Let"s see how we get our hands on a DriveInfo object.
DriveInfo object for computer drive information""># Get a DriveInfo object for computer drive informationAfter we add a reference to the System.IO namespace to our code, there are two ways to get a DriveInfo object (Asad & Ali, 2017; Stephens, 2014):
Regardless of how we fetch drive information, the returned DriveInfo object has several properties that say something about the drive. Let"s see what information those properties give.
DriveInfo properties""># Get drive information with DriveInfo propertiesA DriveInfo object models a computer drive and its properties that tell us something about that drive. The properties are listed in the table below. Some require a ready computer drive before they can query the drive for information. Those properties are highlighted with an asterisk (*).
All DriveInfo properties are (Microsoft Docs, n.d. a; Stephens, 2014):
DriveInfo property | Description |
---|---|
AvailableFreeSpace* | Returns a long value with the drive"s free space in bytes. This value accounts for any drive quota. That means it returns how much free space our application can actually access. See available versus free drive space for more. |
DriveFormat* | Returns the name of the file system as a string, like "NTFS" (NT File System) or "FAT32" (32-bit File Allocation Table). |
DriveType | Returns a value from the DriveType enumeration (with integer as underlying value) that indicates the kind of drive. Possible values for this property are CDRom, Fixed, Network, NoRootDirectory, Ram, Removable, or Unknown. |
IsReady | Returns true when the drive is ready, and false when it isn"t. Several DriveInfo properties depend on a ready computer drive, and throw an exception when we access them while IsReady is false. |
Name | Returns the root name of the drive as a string value (like "C:\" or "E:\"). |
RootDirectory | Returns a DirectoryInfo object that represents the drive"s root directory. We take a closer look at this property in get directory information from a drive. |
TotalFreeSpace* | Returns a long value with the drive"s total amount of free space in bytes. This property ignores any disk quotas. That means the total free space that it returns is not necessarily the amount of free space that the current computer user can access. See free and available drive space in C# for more. |
TotalSize* | Returns a long value with the drive"s total size (meaning, its capacity) in bytes. |
VolumeLabel* | Gets or sets a drive"s volume label with a string, like "Windows" or "Backup drive". This property accepts null values. It triggers an exception when we set the volume label of a network or CD-ROM drive. The length of the volume label depends on the operating system: a NTFS drive, for instance, may have a label up to 32 characters long. |
An inactive computer drive can take a second or two to spin up. That means it can take a bit of time before a DriveInfo property returns information. Our program will temporarily pause while it waits on that information – unless you query drive information from a different thread than the one the application runs on.
Several DriveInfo properties require a ready computer drive. The IsReady property is a quick way to see whether a drive is accessible before we use the drive"s AvailableFreeSpace, DriveFormat, TotalFreeSpace, TotalSize, or VolumeLabel property.
If we don"t check if a drive is ready before we use one of those properties, C# throws an IOException exception (saying “the device is not ready”) when the drive is inaccessible (Hilyard & Teilhet, 2015; Microsoft Docs, n.d. c). See handle inaccessible computer drives in C# for more.
With the IsReady property we check if a drive can be queried for information. But its value is only accurate the moment we look up the property. After that the property can quickly change.
That can make the property an unreliable way to handle drives that might disconnect during a long-running program, like USB drives. See error handling for inaccessible drives for a better alternative.
Now let"s learn how we can use the DriveInfo class in a few programming examples.
# Example: use C# to get info from a particular computer driveTo fetch drive information from a specific computer drive we first need an instance of the DriveInfo class. We can make one with the DriveInfo() constructor, which has one required argument: a string value with the drive letter.
That string argument has these features (Microsoft Docs, n.d. b):
Here"s a console application example program that uses the DriveInfo() constructor to fetch drive information:
This example program outputs various details of the computer"s D:\ drive:
Drive name: D:\ Drive type: Fixed Drive format: NTFS Total size: 250056704000 Total free space: 137174052864 Available free space: 137174052864Let"s walk through the code and see how we got this drive information. First we made an instance of the DriveInfo class:
Here we call DriveInfo() and pass it the "D" argument. That has the class constructor make a DriveInfo instance for the D:\ drive. We store that object in the dDrive variable to later query that drive for information.
Next we use that variable to output drive information:
Not all drives are accessible all the time (a USB drive can, for instance, be removed while our program runs). And so this if statement first checks the IsReady property to see if the drive is accessible at this time. When it is, IsReady returns true.
Inside the if statement"s code block we have several Console.WriteLine() statements. The first outputs the drive"s name with the Name property. Then we show the drive type with the DriveType property, which returns an enumerated value like Fixed, Removable, or CDRom. We also print the file system format with DriveFormat. That property returns values like ‘NTFS’ or ‘FAT32’.
Then we output information about the drive"s size and free space. We get the first with the TotalSize property, which returns the drive"s total amount of space in bytes. We use TotalFreeSpace to show the total amount of free space in bytes, while AvailableFreeSpace prints the free space in bytes that"s available to the current computer user. (See the difference between TotalFreeSpace and AvailableFreeSpace to learn more.)
DriveInfo() exceptions""># Tip: get robust C# code by handling possible DriveInfo() exceptionsIn the above example we used the DriveInfo() constructor to make a DriveInfo instance for the D:\ drive. We then used that object to fetch various drive information.
Since we hard-coded the "D" drive letter into the code, we knew for sure that this string value worked with the DriveInfo() constructor. But when we got that drive letter from somewhere else (like a file or user input), we can"t be sure that the string is a valid drive letter.
The DriveInfo() constructor can trigger two exceptions for invalid drive letters (Microsoft Docs, n.d. b):
Because of these exceptions, we better implement some error handling when we call DriveInfo(). That way an invalid string argument does not immediately crash our program.
A basic pattern for that is the following:
Here we make a custom method named GetComputerDrive() for easy access and no code duplication. Inside the method"s try code block we return a new DriveInfo instance based on the method"s driveLetter argument.
Should the DriveInfo() constructor error, the catch code block handles any ArgumentException exception. There we have Console.WriteLine() print the error message. Other things we can code in this catch code is use a default value, log the error in a file, or ask the user to provide another drive letter.
The DriveInfo() constructor can trigger two exceptions: ArgumentNullException and ArgumentException. But since ArgumentNullException inherits from ArgumentException, a single catch block for ArgumentException catches both exceptions (Stephens, 2014).
Of course, you can still use a specific ArgumentNullException catch code block to explicitly handle those situations in which the DriveInfo() argument is null.
See handle removed or disconnected drives in C# for other ways to make our code more robust with try/catch code.
# Example: loop through all computer drives with C#In the previous example we fetch information from a specific drive. But we can also get a collection of all computer drives in C#. We do that with the DriveInfo.GetDrives() method, which returns an array with DriveInfo objects that each represent a single computer drive (Microsoft Docs, n.d. c).
Here"s an example console application program that prints information for each computer drive:
This is the output the program generates on my computer:
Drive information for all 3 drives: Drive: C:\ (NTFS, Fixed) Available free space: 16935489536 bytes Total free space: 16935489536 bytes Total drive size: 119926681600 bytes Drive: D:\ (NTFS, Fixed) Available free space: 137174052864 bytes Total free space: 137174052864 bytes Total drive size: 250056704000 bytes Drive: E:\ (FAT32, Removable) Available free space: 155123712 bytes Total free space: 155123712 bytes Total drive size: 254312448 bytes Press a key to close this window..Let"s walk through the code to see what it does. First we fetch all computer drives:
Here we made a DriveInfo array named allDrives. We set that array to the drives returned by the static and parameterless DriveInfo.GetDrives() method. Then Console.WriteLine() outputs the number of drives. We get that information by simply using the array"s Length property.
Then we loop through all computer drives in that array:
This foreach loop goes through all elements in the allDrives array. The loop"s drive variable represents a single DriveInfo object with each iteration through the loop.
Inside the loop an if statement checks whether the drive is ready. When it"s not and IsReady returns false, the if statement executes the continue keyword to skip the current loop cycle. This way the DriveInfo properties we use later in the loop don"t error because of an unready drive.
The remaining code in the loop are Console.WriteLine() statements that print drive information. We output the drive"s name (Name), its file system format (DriveFormat), and the kind of drive, like fixed or removable (DriveType).
Then we print the free space our application can use (AvailableFreeSpace). We use the drive"s TotalFreeSpace property to display the total amount of free disk space. And with TotalSize we show the drive"s total capacity in bytes.
DriveInfo.GetDrives()""># Tip: manage possible exceptions triggered by DriveInfo.GetDrives()In the above example we iterated over all computer drives with the DriveInfo.GetDrives() method. And while that worked fine, DriveInfo.GetDrives() is not a fail-safe method.
There are two exceptions that can happen with DriveInfo.GetDrives() (Microsoft Docs, n.d. c):
When these exceptions go unhandled, they immediately crash our program. And so our C# code become more robust when we handle possible DriveInfo.GetDrives() errors.
One way to do that is with the following method:
This method returns an array of DriveInfo objects. In the try code block we call the DriveInfo.GetDrives() method. If that method call succeeds, our GetComputerDrives() method returns the array of DriveInfo objects that DriveInfo.GetDrives() returned.
If something went wrong with DriveInfo.GetDrives(), two catch code blocks handle exceptions. The first catches any IOException errors caused by inaccessible drives. The other handles UnauthorizedAccessException problems that happen when our drive has insufficient permissions.
In the above method we use simple Console.WriteLine() statements to print error information, but your application can also log the errors, fail silently, use a default value, or retry at a later point. See handle removed or disconnected drives for more ways to make C# computer drive code more robust.
# SummaryAn instance of the DriveInfo class represents a single computer drive. Once we have such an object we can use its properties to fetch drive information. There are two ways to get our hands on a DriveInfo object.
We use the DriveInfo() constructor to get a single DriveInfo object. For that we pass that method a string argument with the drive letter. An alternative is the DriveInfo.GetDrives() method, which returns an array with a DriveInfo object for each drive the computer has.
There are two groups of DriveInfo properties: those that we can access at any time and those that require a ready drive. The properties we can fetch whenever we want return the drive"s name (Name), type of drive (DriveType), root directory (RootDirectory), and whether the drive is ready or not (IsReady).
The properties that depend on a ready drive return the drive"s accessible free space (AvailableFreeSpace), the total free space (TotalFreeSpace), and its capacity (TotalSize). The file system format (DriveFormat) and volume label (VolumeLabel) also depend on a ready drive.
To see whether a drive is ready to be queried for information we use the IsReady property. That one returns true when the drive is accessible and false when unavailable.
Asad, A. & Ali, H. (2017). The C# Programmer"s Study Guide (MCSD). New York, NY: Apress.
Hilyard, J. & Teilhet, S. (2015). C# 6.0 Cookbook (4th edition). Sebastopol, CA: O’Reilly Media.
Microsoft Docs (n.d. a). DriveInfo Class. Retrieved on July 23, 2018, from https://docs.microsoft.com/en-us/dotnet/api/system.io.driveinfo?view=netframework-4.7.1
Microsoft Docs (n.d. b). DriveInfo(String) Constructor. Retrieved on July 23, 2018, from https://docs.microsoft.com/en-us/dotnet/api/system.io.driveinfo.-ctor?view=netframework-4.7.1#System_IO_DriveInfo__ctor_System_String_
Microsoft Docs (n.d. c). DriveInfo.GetDrives Method. Retrieved on July 23, 2018, from https://docs.microsoft.com/en-us/dotnet/api/system.io.driveinfo.getdrives?view=netframework-4.7.1#System_IO_DriveInfo_GetDrives
MSDN Microsoft Developer Network (n.d.). DriveInfo Class. Retrieved on July 23, 2018, from https://msdn.microsoft.com/en-us/library/system.io.driveinfo(v=vs.110).aspx
Stephens, R. (2014). C# 5.0 Programmer Reference. Indianapolis, IN: John Wiley & Sons.
We access computer drive information with C#‘s DriveInfo class. With that class’ RootDirectory property we access the drive"s top-level directories.
C#‘s DriveInfo.GetDrives() method returns all computer drives. With LINQ extension methods and lambda expressions we can filter those programmatically.
A computer drive that becomes inaccessible while our program runs triggers an exception. To not crash our C# program we handle those with try/catch.
C# can change a drive"s volume label. For that we first make an instance of the DriveInfo class. Then we update that drive"s VolumeLabel property.
C#‘s DriveInfo class has two similar properties: AvailableFreeSpace and TotalFreeSpace. The first accounts for disk quotas while the second does not.