Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Get a list of physical disks and the partitions on them in VB.NET the easy way

4.75/5 (4 votes)
8 Jun 2012CPOL2 min read 64.3K   2.8K  
Use DeviceIoControl, QueryDosDevice and WNetOpenEnum to get information about your system.

 Image 1

Introduction

Have you ever needed to know how many hard disks there are in the computer your app is running on? Which partitions are on which hard disks? Which drives are network drives, and what their UNC paths may be? What the dos name and number of the CD/DVDRoms in the system may be? In this example project you will find the class clsDiskInfoEx - which is a compilation of code I use to accomplish these ends. This code runs correctly on Windows 7, Vista, 2003 and XP. 

Background  

Recently I've been working on code to accomplish faster file copies in Windows. There are some 3rd party utilities, I know - but I wanted to be able to integrate this into my code. Eventually I found myself trying to figure out why concurrent reading and writing sometimes slowed things down. A little searching revealed the ugly truth - that reading and writing to the same hard drive concurrently was the problem. I set about trying to figure out which partitions were on the same hard drive to compensate, and this class was the result. 

This code was not entirely written by me - jo0l's .NET stuff and pinvoke.net were great starting points, and if you haven't already you should check them out.

Using the code  

  • clsDiskInfoEx does quite a bit behind the scene, and has several useful methods. Instantiate it with new the way you normally would with any class.
  • GetNetworkComputers - Returns a list(Of String) of the available computers in your network.
  • GetNetworkDrives - Returns a list(Of String) of network drives and their UNC paths, separated by "=".
  • GetUncPathOfMappedDrive - I think this is self explanatory.
  • GetPhysicalDisks - returns a list(Of String) of all the drives in the system and their respective parent device, be it an Physical disk, UNC path or dos CD Rom number formatted as follows: "C:=\\.\PhysicalDisk0"
  • GetPhysicalDiskParentFor(logicalDisk As String) As String - This is the one that gets all the use in this example project. When you instantiate the class, it fills an internal list with information about all the drives in your system. Feed this method the root directory of a drive (i.e.: "c:\") and it gives you the parent drive for that partition. To update the disk information (i.e.: someone plugged in a flash drive or inserted a CD), use the Refresh() method.

Here's a quick look at the code that adds the drive information into a listview in the example project's main form:

VB
Private Sub GetDriveInfo()
 
    Dim count As Int32 = 0
    Dim driveInfoEx As New clsDiskInfoEx
    Dim multipleParents() As String = Nothing
    Dim parentDrives As String = Nothing

    lvDriveInfo.Items.Clear()

    For Each drive As System.IO.DriveInfo In System.IO.DriveInfo.GetDrives

        parentDrives = driveInfoEx.GetPhysicalDiskParentFor(drive.RootDirectory.ToString)
        If parentDrives.Contains(", ") Then
            ' We have multiple parent drives:
            multipleParents = Split(parentDrives, ", ")
            ' Enumerate them backwards so the lowest numbered drives are reported 1st
            For more As Int32 = (multipleParents.Length - 1) To 0 Step -1
                If more = (multipleParents.Length - 1) Then
                    lvDriveInfo.Items.Add("")
                    lvDriveInfo.Items(count).SubItems.Add(drive.RootDirectory.ToString.Replace("\", ""))
                    lvDriveInfo.Items(count).SubItems.Add(multipleParents(more)) ' Parent drive
                    lvDriveInfo.Items(count).SubItems.Add(drive.DriveType.ToString)

                    If drive.IsReady Then
                        lvDriveInfo.Items(count).SubItems.Add(drive.DriveFormat)
                        lvDriveInfo.Items(count).SubItems.Add((drive.TotalSize / 1000000).ToString("N0") & " MB")
                        lvDriveInfo.Items(count).SubItems.Add((drive.AvailableFreeSpace / 1000000).ToString("N0") & " MB")
                    Else
                        lvDriveInfo.Items(count).SubItems.Add("No Disc")
                        lvDriveInfo.Items(count).SubItems.Add("-")
                        lvDriveInfo.Items(count).SubItems.Add("-")
                    End If
                Else
                    count += 1
                    lvDriveInfo.Items.Add("")
                    lvDriveInfo.Items(count).SubItems.Add(drive.RootDirectory.ToString.Replace("\", ""))
                    lvDriveInfo.Items(count).SubItems.Add(multipleParents(more)) ' Parent drive
                    lvDriveInfo.Items(count).SubItems.Add("Mirror or Span")
                    If drive.IsReady Then
                        lvDriveInfo.Items(count).SubItems.Add(drive.DriveFormat)
                    Else
                        lvDriveInfo.Items(count).SubItems.Add("")
                    End If
                    lvDriveInfo.Items(count).SubItems.Add("-")
                    lvDriveInfo.Items(count).SubItems.Add("-")
                End If
            Next
            count += 1
        Else
            ' Just one parent drive for this partition.
            lvDriveInfo.Items.Add("")
            lvDriveInfo.Items(count).SubItems.Add(drive.RootDirectory.ToString.Replace("\", ""))
            lvDriveInfo.Items(count).SubItems.Add(parentDrives) ' Parent drive
            lvDriveInfo.Items(count).SubItems.Add(drive.DriveType.ToString)

            If drive.IsReady Then
                lvDriveInfo.Items(count).SubItems.Add(drive.DriveFormat)
                lvDriveInfo.Items(count).SubItems.Add((drive.TotalSize / 1000000).ToString("N0") & " MB")
                lvDriveInfo.Items(count).SubItems.Add((drive.AvailableFreeSpace / 1000000).ToString("N0") & " MB")
            Else
                lvDriveInfo.Items(count).SubItems.Add("No Disc")
                lvDriveInfo.Items(count).SubItems.Add("-")
                lvDriveInfo.Items(count).SubItems.Add("-")
            End If
            count += 1
        End If
    Next
End Sub

Points of Interest

This class also correctly reports partitions that span drives, like mirrors, stripes or spanned volumes. However, it has only been tested in a machine with mirrored drives. If it behaves badly in systems with alternate configurations, I'd love to know it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)