Inventory Drive Types by Using PowerShell


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to detect drive types.

Hey, Scripting Guy! Question Hey, Scripting Guy! We have a number of workstations in our network. Many of the users bring USB keys from home to transfer their files. Others have large external USB drives attached to their machines, and others have portable CD/DVD devices attached. I need to come up with some kind of inventory so I see how prevalent this situation really is. Can Windows PowerShell help?

—OG

Hey, Scripting Guy! Answer Hello OG,

Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sitting on the porch sipping a nice cup of English Breakfast tea. I decided to make it a mint tea today, so I added peppermint leaf, spearmint leaf, licorice root, and a cinnamon stick for sweetness and flavor. The result is a nice refreshing cup of tea. I am checking scripter@microsoft.com email on my Surface Pro 3, and enjoying the sunrise.

OG, yes indeed, Windows PowerShell can help you identify drive types. You can use the Get-Volume cmdlet (in Windows 8.1 or Windows 8). This works well, and it will automatically translate your drive type for you. In addition, it provides access to other information. Here is an example of this command:

PS C:\> Get-Volume

DriveLetter FileSystemL FileSystem  DriveType  HealthStat SizeRemain       Size

            abel                               us                ing          

———– ———– ———-  ———  ———- ———-       —-

C           SSD         NTFS        Fixed      Healthy      75.38 GB  148.53 GB

E           HybridTe… NTFS        Fixed      Healthy     560.71 GB  931.39 GB

D           FourTB_B… NTFS        Fixed      Healthy        1.5 TB    3.64 TB

F           TwoTB_BU… NTFS        Fixed      Healthy     204.34 GB    1.82 TB

G           USB3        NTFS        Removable  Healthy       6.73 GB   58.89 GB

            Recovery    NTFS        Fixed      Healthy      22.96 MB     300 MB

H                                   CD-ROM     Healthy           0 B        0 B

But if you have machines that are running previous versions of Windows, such as desktops and laptops that are running Windows 7, you need to use a different technique. This is where WMI comes into play.

I am going to assume that you have upgraded your Windows 7 machines to Windows PowerShell 3.0 (or preferably, Windows PowerShell 4.0) so that you can use the super-fast CIM cmdlets. If you have not upgraded Windows PowerShell yet, you need to use the Get-WmiObject cmdlet instead of using Get-CimInstance.

The nice thing about the Get-Volume cmdlet is that it automatically translates the coded value for disk type into a string that lets me know if the drive is fixed, removable, or a CD-ROM. When I write my own script, I need to do the translation myself.

Win32_LogicalDisk

The WMI class I am going to use is the Win32_LogicalDisk class. It is documented on MSDN: Win32_LogicalDisk class. Probably the key item to pay attention to is the enumeration values for DriveType. There are six values listed in the article. I am adding only three of them.

The first thing I do is create a hash table to store my enumeration keys and my associated values:

$hash = @{

   2 = "Removable disk"

   3="Fixed local disk"

   4="Network disk"

   5 = "Compact disk"}

Now I query the Win32_LogicalDisk WMI class by using the Get-CimInstance cmdlet. This is really easy, as shown here:

Get-CimInstance Win32_LogicalDisk

The actual tricky part of my script is where I use the Select-Object cmdlet, and I create a custom property that looks up the enumeration numeric value and changes it to a string that I can understand.

Note  This was actually annoying, and it took me more than 15 minutes to figure out. The reason? It seems that the number returned is actually a string and not an integer. Therefore, my lookup was failing. This was easily solved by casting it to [int]—after I figured out what was happening. So be wary when getting values from WMI. Often they are not what you would actually think they might be.

The complete script is shown here:

$hash = @{

   2 = "Removable disk"

   3="Fixed local disk"

   4="Network disk"

   5 = "Compact disk"}

Get-CimInstance Win32_LogicalDisk |

Select DeviceID, VolumeName,

@{LABEL='TypeDrive';

EXPRESSION={$hash.item([int]$_.DriveType)}}

Here is the script and associated output in the Windows PowerShell ISE:

Image of command output

OG, that is all there is to using Windows PowerShell to detect drive types. WMI Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (5)

  1. tommymaynard says:

    The Win32_LogicalClass will return USB drives, SD cards, and possibly others as the same. I wrote a function that allow someone to be 100% sure the drive is USB connected. Check it out on the TechNet Gallery here:

    http://gallery.technet.microsoft.com/Map-Drive-to-Drive-Letter-1fff91ad

  2. Paul Goffar says:

    Mr. Wilson,

    I have a similar project to work on and I’m hoping you may shed some light. I have a need to audit mapped drives and I’m looking to add a column in my CSV which will display $ENV:USERNAME and (Get-Date -format g) in addition to the properties that I’m exporting.

    Please see below

    function Get-netdrive
    {
    [CmdletBinding()]
    Param (
    [Parameter(Mandatory = $False, ParameterSetName = ‘OutputPath’)]
    [String]$CSVPath = "\serversharejunk.csv"
    )

    function GetDriveType($DriveCode)
    {
    switch ($DriveCode)
    {
    0 { "Unknown" }
    1 { "No root directory" }
    2 { "Removable Disk" }
    3 { "Local Disk" }
    4 { "Network Drive" }
    5 { "Compact Disk" }
    6 { "RAM Disk" }
    } # end switch
    } # end function GetDriveType

    #LogPath
    $date = (Get-Date).tostring("yyyyMMdd")
    $log = ("\serverfolderfolder" + $ENV:COMPUTERNAME + "_" + $date + ".csv")

    Write-Host "Polling for data…Please standby"

    $output = ‘DeviceID’, ‘ProviderName’,`
    @{ n = ‘DriveType’; e = { GetDriveType($_.driveType) } }, `
    @{ n = ‘Size’; e = { "{0:F2} GB" -f ($_.Size / 1gb) } }, `
    @{ n = ‘FreeSpace’; e = { "{0:F2} GB" -f ($_.FreeSpace / 1gb) } }

    Get-WmiObject -Class win32_logicaldisk |`
    Select-Object $output |`
    Export-Csv -Path $Log -NoTypeInformation -Force -Verbose

    Write-Host "All logical mapped drives were successfully retrieved."
    }

    Get-netdrive -CSVPath $log

  3. Shawne Beeson says:

    How does this see SAN connected disks?

  4. M P says:

    Great sample. Looks like you have four Drive Types defined but you said you only chose three from the list of 6 in your write up.

  5. Jared Terrell says:

    What about sub-mounted volumes – how do you get that free space ?

Skip to main content