Return Only the Fixed Disks

As a part of a recent engagement (with a company you've likely heard of), we had some code written and provided to us. In my review of what was provided to scan drives using Windows Defender, I noticed that there were some problems. One, there was an assumption that a computer would only ever have a single optical drive, and two, mapped network drives may have ended up being scanned, as well. Now, I'm not sure if Defender would actually scan a network drive, but I assume it would and don't really care to find out.

We needed a way to filter out optical drives and network mapped drives regardless of the count of either, before we started a Windows Defender scan. I'll start with the code I used, followed by a second option that occurred more recently -- it was a would this work idea. It does, so I'll explain them both and perhaps we'll all be better for seeing two different options. Before we get deeper into this, take a look at the output provided by Get-PSDrive (when piped to Format-Table and the AutoSize parameter). Clearly, it's found a good number of drives on my system.

PS > Get-PSDrive | Format-Table -AutoSize

Name     Used (GB) Free (GB) Provider    Root                      CurrentLocation
----     --------- --------- --------    ----                      ---------------
Alias                        Alias
C           698.18    232.15 FileSystem  C:\                           Users\tommy
Cert                         Certificate \
D                            FileSystem  D:\
E                            FileSystem  E:\
Env                          Environment
Function                     Function
HKCU                         Registry    HKEY_CURRENT_USER
HKLM                         Registry    HKEY_LOCAL_MACHINE
MDI                          FileSystem  \\mydomain.com\data\in...
MDT                          FileSystem  \\mydomain.com\data\to...
I           112.80    352.96 FileSystem  I:\
P             0.15    465.60 FileSystem  P:\
Variable                     Variable
W           676.59    254.92 FileSystem  W:\
WSMan                        WSMan

Now, let's modify our command and only return our FileSystem drives. Unfortunately, there's a couple of optical drives (although you don't really know that yet), and two mapped network drives that we don't want or need in our results.

PS > Get-PSDrive -PSProvider FileSystem | Format-Table -Autosize

Name     Used (GB) Free (GB) Provider    Root                      CurrentLocation
----     --------- --------- --------    ----                      ---------------
C           698.18    232.15 FileSystem  C:\                           Users\tommy
D                            FileSystem  D:\
E                            FileSystem  E:\
MDI                          FileSystem  \\mydomain.com\data\in...
MDT                          FileSystem  \\mydomain.com\data\to...
I           112.80    352.96 FileSystem  I:\
P             0.15    465.60 FileSystem  P:\
W           676.59    254.92 FileSystem  W:\

In this next example, we'll remove the mapped drives from our results. In the end, we have our fixed drives and the D:\ and E:\ drives that have no used or free space. Perhaps those are the optical drives and there's no actual disks in either one. Before we move past this example, however, let's get the results of this command into a variable, as well. The $FixedDrives variable is assigned toward the bottom of the below example.

PS > Get-PSDrive -PSProvider FileSystem | Where-Object -Property Root -notlike '\\*' | Format-Table -Autosize

Name     Used (GB) Free (GB) Provider    Root CurrentLocation
----     --------- --------- --------    ---- ---------------
C           698.18    232.15 FileSystem  C:\      Users\tommy
D                            FileSystem  D:\
E                            FileSystem  E:\
I           112.80    352.96 FileSystem  I:\
P             0.15    465.60 FileSystem  P:\
W           676.59    254.92 FileSystem  W:\

PS > $FixedDrives = Get-PSDrive -PSProvider FileSystem | Where-Object -Property Root -notlike '\\*'
PS > # Noticed we removed Format-Table -- that was _only_ there for the onscreen display.

Now, let's get a hold of our optical drives. Because we'll need them in a variable, we'll go ahead and make that assignment in this next example, as well.

PS > Get-WmiObject -Class Win32_CDROMDrive | Format-Table -AutoSize

Caption                           Drive Manufacturer             VolumeName
-------                           ----- ------------             ----------
ASUS DRW-1814BLT ATA Device       D:    (Standard CD-ROM drives)
ELBY CLONEDRIVE SCSI CdRom Device E:    (Standard CD-ROM drives)

PS > $OpticalDrives = Get-WmiObject -Class Win32_CDROMDrive

Now that that's done  -- oh look, it is the D:\ and E:\ drives -- let's run a comparison against the fixed drives and optical drives we've returned. Again, this first example is how I rewrote the code that was provided to us. Once we've seen this, then we'll try the comparison I considered over some recent weekend. This example compares the Get-PSDrive's Root property (with the backslash removed) against the Get-WmiObject's Drive property. If they don't match, it stays. Otherwise, it's filtered out. As you'll see, when we assign and return our new $DrivesToTest variable, we can see that our D:\ and E:\ drives -- our optical drives -- have been removed. Perfect.

PS > $DrivesToTest = ($FixedDrives.Root).TrimEnd('\') | Where-Object {$OpticalDrives.Drive -notcontains $_}
PS > $DrivesToTest
C:
I:
P:
W:

Let's use our $FixedDrives and $OpticalDrives variables again, but this time with the Compare-Object cmdlet. This was the additional idea I had to determine if we can simplify things even more. As some have noticed -- I have not shied away from the fact that I tend to do things the hard way, the first time. In case it makes a difference, and I hope it doesn't, Compare-Object was first introduced in PowerShell 3.0.

PS > (Compare-Object -ReferenceObject ($FixedDrives.Root).TrimEnd('\') -DifferenceObject $OpticalDrives.Drive).InputObject
C:
I:
P:
W:

Just like that we've got the same results, with less work. Now, I can get back to doing whatever it was before I began reviewing this code. That and our users can safely get to work scanning machines with Windows Defender, without the concern anyone will scan against any number of optical drives, or mapped network drives.

≥ Tommy Maynard (Twitter: @thetommymaynard)

About Tommy Maynard

IT Pro. Passionate for #PowerShell, #AWS (certified x2), & all things automation. I'm not done learning. Author in #PSConfBook. Writes at https://powershell.org.

4 thoughts on “Return Only the Fixed Disks

    1. Tommy Maynard (tommymaynard) Post author

      Hey Christian,

      This is an awesome addition to this article. It's quick, clean, and gets everything that's necessary, and all in a single shot. I worked with the code I had been provided without consideration for complete, one-step options, it seems. All that said, I did appreciate the opportunity to better the code that was provided, just like you did, with what I provided you. And to think, I've seen DriveType 3 plenty of times in the past. Thanks for the comment!

      Tommy

  1. ztaps56

    Great article Tommy. Nice and easy to follow.

    Expanding on your code, I would suggest we could maybe also assume Used (GB) and Free (GB) must be non null and filter on that additional criteria to get the equivalent results above.

    Get-PSDrive -PSProvider FileSystem | ? {($_.used) -and ($_.root -notlike '\\*')} | ft -auto

    cheers

Comments are closed.