Use Get-CIMInstance to Create a PowerShell File Extension Report

I love seeing what other people are doing with PowerShell. That is why I keep an eye on the #PowerShell hashtag on Twitter. I always find something interesting and useful. Often, I even learn something new. Usually when I find something new and intriguing, I decide to see what I can do with it. I am always interested to see how I can take an example and expand it. Not too long ago I came across a blog post via Twitter that used Get-CIMInstance to retrieve a list of fixed hard drives and then create a file extension report for all files on that drive. I thought it was nicely done and a clever way to combine different commands. It inspired me to see how far I could take these techniques.

Using the Get-CimInstance Cmdlet

Using Get-CimInstance is the modern way of accessing Windows Management Instrumentation (WMI) information. This is especially true because it is easy to query remote computers. One drawback to the original code was that it used Get-ChildItem to enumerate all files on the specified drive. That works fine locally but not remotely. You could wrap the entire command in scriptblock and run it remotely with Invoke-Command. But I thought since we’re using WMI already, why not use WMI to query for all the files? We can accomplish this using the CIM_Datafile class.

Here is a sample that finds all files on my E: drive grouped by the Extension property.

The output is similar to the inspiring article where I include a custom property to measure all of the files for each extension and format the result in MB to four decimal places. Note that the property I’m measuring is Filesize and not length, because I have CIM_Datefile objects, not System.IO.FileInfo. Here’s a sample instance.

Given all of that, here’s my result.

Results of Get-CIMInstance in Windows PowerShell. (Image Credit: Jeff Hicks)
Results of Get-CIMInstance in Windows PowerShell. (Image Credit: Jeff Hicks)

I saved the output of the Get-CimInstance expression to a variable $e by using the common Out-Variable parameter. It has an alias of ov.

This way I can re-use the results without having to re-run a potentially long command. Let’s say I want to find the top ten most used extensions.

Top 10 most used extensions. (Image Credit: Jeff Hicks)
Top 10 most used extensions. (Image Credit: Jeff Hicks)

Or I can group by something else. For example, I see a property called FileType. Let’s group and measure results based on that property.

Grouping and measuring results using the FileType property. (Image Credit: Jeff Hicks)
Grouping and measuring results using the FileType property. (Image Credit: Jeff Hicks)

Maybe that is more meaningful to you. If you try this, then you might notice that the query includes hidden and system files. I probably don’t need to count them so I can filter them out.

Note that the values are strings and not the PowerShell boolean values. Now that I have some code that works for a single drive, let’s create a report for all fixed drives.

I’m running this locally for now and saving the results to a text file, but you could easily export to a CSV file or anything else you can think of. This could take some time to run in which case you could always wrap the command in a scriptblock and use Start-Job.

The benefit of using Get-CimInstance is that I can use this command to query a remote computer.

Although, all of the processing of grouping and selecting is happening on my computer after I retrieve the results. Depending on the situation it might make more sense to have the remote computer do the work. Especially if I am querying multiple machines.

In this situation, since I know the remote computer supports PowerShell remoting, I can use a PSSession. I’ll define a scriptblock to only search the C: drive for files.

Next I can create some PSSessions, or I could just use computernames.

Finally, I’ll use Invoke-Command, and I’ll execute it as a background job because this could take a while to run.

When the job is complete I can receive the results.

I can format the results anyway I need:

I’m not implying that any of these examples are the best or only way to accomplish this task. But I think it is important that you experiment with different techniques and use Measure-Command to help identify which performs the best in our environment.

If you get stuck with any of my examples, please post a problem in the PowerShell forum on the site. I also hope you’ll keep an eye out on Twitter and other platforms for interesting PowerShell tidbits that you can take and re-purpose into something that makes your job easier.

Related Topics:

  • PowerShell

    Don't have a login but want to join the conversation? Sign up for a Petri Account