Using PowerShell and WMI to Find Folders by File Type

Posted on March 3, 2015 by Jeff Hicks in PowerShell with 0 Comments

We recently published an article about how to use PowerShell to find folders that contain a certain file type, such as the MP3 file format. I showed you how to search the file system using the DIR command. Although this command works fine when run locally, it might not perform very well if you want to search an entire drive. If you want to search remote computers, then querying the file system and even using PowerShell remoting with Invoke-Command is less than optimal. If you are targeting a specific root folder, it might not be that bad, but using Get-ChildItem (DIR) doesn’t scale very well, in my opinion. As an alternative, you can use Windows Management Instrumentation (WMI).

It turns out that WMI can search for files just as easily by querying instances of the CIM_Datafile class. From experience, I know that you should use the most targeted filter you can. This means you need to know property names.

The out-gridview for get-cimclass. (Image Credit: Jeff Hicks)

The out-gridview for get-cimclass. (Image Credit: Jeff Hicks)

Here is an actual instance.

Let’s start by querying locally, again looking for folders that contain MP3 files under C:\work. Here’s my query.

I find that these types of queries perform best if I limit the search to a specific drive. You can also see where I’m filtering for the file extension. Note that there is no period. The trickiest part is the path component, where I’m using the LIKE operator and the wildcard (denoted by ‘%’) to retrieve any instance where the path starts with \work\. In WMI, you need to escape the backward-slash character (denoted by ‘\’), which is why I end up with \\work\\. In a WMI filter, use a wildcard instead of an asterik. My command writes results to the pipeline and saves the results to a variable, $m, so that I can look at them later without having to re-run the command.

Using Get-CimInstance in Windows PowerShell. (Image Credit: Jeff Hicks)

Using Get-CimInstance in Windows PowerShell. (Image Credit: Jeff Hicks)

Remember, my goal is to get the directory name. As you can see from my full sample instance above, you could try to parse out a value. Instead, we’ll have WMI do the work. In WMI, classes are often associated with other classes. In this case, each of these data file objects has a corresponding association to a Win32_Directory type of object. The CIM cmdlets make it very easy to retrieve this information.

Using WMI to parse out values in PowerShell. (Image Credit: Jeff Hicks)

Using WMI to parse out values in PowerShell. (Image Credit: Jeff Hicks)

Again, $m holds the results from the Get-CimInstance cmdlet. Now I have Win32_Directory objects at the end of the pipeline. I should probably filter out duplicates and sort my results.

Win32_Directory object results. (Image Credit: Jeff Hicks)

Win32_Directory object results. (Image Credit: Jeff Hicks)

Now for the fun part. I have an expression that works locally. Let’s scale out and search remote computers. An advantage of using Get-CIMInstance is that the request goes out over WSMan, which means I only need to worry about a single port. No DCOM or SMB traffic needs to go over the wire.

Sponsored

I want to search for ZIP files under C:\Work on CHI-CORE01 and get the matching folder paths.

The result of our PowerShell search. (Image Credit: Jeff Hicks)

The result of our PowerShell search. (Image Credit: Jeff Hicks)

I included the computer name in the result, so I would know where to look. I can also modify my filter and search the entire C:\ drive.

This is much faster than using the DIR command and searching C: recursively.

If I can search one computer, I can just as easily search multiple computers.

The out-gridview for zip files. (Image Credit: Jeff Hicks)

The out-gridview for zip files. (Image Credit: Jeff Hicks)

In this article, I have been using the CIM cmdlets, which assumes you are running PowerShell 3.0 or later locally and remotely.

Sponsored

If you don’t have access to these cmdlets, then you can use the legacy Get-WMIObject cmdlet. There’s no cmdlet for retrieving associations. Instead, you will need to invoke the GetRelated() method. I’m using the resulting class name, Win32_Directory, as a parameter to limit the results.

The result is the same WMI information.

Using the GetRelated() method in PowerShell to retrieve associations. (Image Credit: Jeff Hicks)

Using the GetRelated() method in PowerShell to retrieve associations. (Image Credit: Jeff Hicks)

With that said, hopefully you can use the CIM cmdlets. It wouldn’t take much to turn this into a PowerShell tool that you could re-use. Although I’ve been focusing on the associated Win32_Directory class, you might be interested in the CIM_Datafile class. If you have question on any of this or run into issues building your own tools, I encourage you to use the PowerShell forum on the Petri IT Knowledgebase.

Sponsored

Tagged with , , , , , ,