PowerShell Problem Solver: More with Negatives

tiny-people-working-on-computer-hero-img
In a previous PowerShell Problem Solver, I tackled the problem of documenting something that isn’t there, namely a specific service. The original online post I came across had a second problem that falls into the same category. Although it’s probably true that all volumes on all servers are configured for NTFS, he had to prove it. I took this also as a challenge to identify volumes and servers that don’t meet the criteria. As with all of these articles, pay more attention to techniques and ideas than necessarily to the final result.


As in my previous article, I have a variable with a list of server names that I know are running and that I can access. You would need to include error handling into your solution, but I don’t want that to complicate the situation or distract you. I’ve also decided that I’m only interested in logical drives and not necessarily all volumes. This means I will use the Win32_Logicaldisk class with Get-CimInstance, but you could easily use Win32_Volume in its place.
I’ll start with a simple command like this:

Get-CimInstance win32_logicaldisk -computer $servers |
select Caption,FileSystem,Volumename,PSComputername

Listing logical disks with WMI and PowerShell (Image Credit: Jeff Hicks)
Listing logical disks with WMI and PowerShell (Image Credit: Jeff Hicks)

Although this isn’t the final result, it helps me narrow down the problem. In this case, I want to only identify servers with NTFS, which should also mean I can revise my command to include a WMI filter.

Get-CimInstance win32_logicaldisk -computer $servers -filter "Drivetype=3" |
select DeviceID,FileSystem,Volumename,PSComputername

Filtered results (Image Credit: Jeff Hicks)
Filtered results (Image Credit: Jeff Hicks)

That’s better. Now I’ve at least documented the volumes and can see that there’s a disk on CHI-TEST02 using Fat32 instead of NTFS. I can take this a step further with a formatted result:

Get-CimInstance win32_logicaldisk -computer $servers -filter "Drivetype=3" |
Sort FileSystem,DeviceID,PSComputername |
Format-Table -GroupBy FileSystem -Property DeviceID,Volumename,PSComputername

The end result is a formatted table grouped by the FileSystem property. I always recommend sorting on the property prior to formatting to get the best results.

Grouped and Formatted results with PowerShell (Image Credit: Jeff Hicks)
Grouped and Formatted results with PowerShell (Image Credit: Jeff Hicks)

If I needed a document to prepare for auditors or management, this would be a good place to start. But perhaps you only want to identify servers not using NTFS. Let PowerShell do the work for you.

Get-CimInstance win32_logicaldisk -computer $servers -filter "Drivetype=3 AND FileSystem<>'NTFS'" |
select DeviceID,FileSystem,Volumename,PSComputername

Remember that with WMI filters we use the legacy operators like the equal sign instead of the newer PowerShell operators. The output is now limited to potential problems.

Finding the odd result
Finding the odd result (Image Credit: Jeff Hicks)

Once you get the hang of filtering, it makes it easy to handle any management request. For example, let’s say that I don’t care if other volumes are not formatted as NTFS, but the C:\ drive must be NTFS. I can document all drives:

Get-CimInstance win32_logicaldisk -computer $servers -filter "DeviceID = 'C:'" |
select DeviceID,FileSystem,PSComputername

Listing drive C and NTFS
Listing drive C and NTFS (Image Credit: Jeff Hicks)


Or find those not using NTFS:

Get-CimInstance win32_logicaldisk -computer $servers -filter "DeviceID = 'C:' AND FileSystem<>'NTFS'" |
select DeviceID,FileSystem,PSComputername

In my case, I get no results, which is a good thing.
To wrap things up, let’s bring back a concept from the previous article. The scenario now is that all of my servers should have a fixed disk for drive D. I need to verify which servers have this drive. It’s simple enough to find those that have the drive.

Get-CimInstance win32_logicaldisk -computer $servers -filter "DeviceID = 'D:' AND Drivetype=3"

Listing Drive D
Listing Drive D (Image Credit: Jeff Hicks)

To see all the servers I need to process them individually. Here’s a variation of some code I used last time:

$servers | foreach {
if (Get-CimInstance win32_logicaldisk -computer $_ -filter "DeviceID = 'D:' AND Drivetype=3") {
  $Verified = $True
}
else {
  $Verified = $False
}
[pscustomobject]@{
  Computername = $_
  Verified = $Verified
 }
} | Sort Verified

With equally useful results:

Verified Results
Verified Results (Image Credit: Jeff Hicks)

Or if I simply want the server name, I can use Where-Object and the –Not operator.

$servers | where { -NOT (Get-CimInstance win32_logicaldisk -computer $_ -filter "DeviceID = 'D:' AND Drivetype=3") }

If the Get-CimInstance command fails, then it won’t write an object to the pipeline, which would be a $False result. Using –Not turns it around to $True so that the computername is passed on to the pipeline.

Negative filtering with Where-Object and -Not
Negative filtering with Where-Object and -Not (Image Credit: Jeff HIcks)

Using Where-Object and the –Not operator would certainly be a viable solution, depending on your needs.

And that’s the biggest takeaway. PowerShell is flexible enough to get the job done in a variety of ways depending on the situation or your end requirements. The more proficient you become with PowerShell the easier it will be for you to develop a solution that works for you.