Last Update: Sep 04, 2024 | Published: Mar 03, 2015
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.
get-cimclass cim_datafile | Select -ExpandProperty CIMClassProperties | Select Name,CimType | out-gridview
Here is an actual instance.
Status : OK Name : c:workabdemo.mp3 Caption : c:workabdemo.mp3 Description : c:workabdemo.mp3 InstallDate : 1/15/2015 8:47:16 AM AccessMask : 18809343 Archive : True Compressed : False CompressionMethod : CreationClassName : CIM_LogicalFile CreationDate : 1/15/2015 8:47:16 AM CSCreationClassName : Win32_ComputerSystem CSName : WIN81-ENT-01 Drive : c: EightDotThreeFileName : c:workabdemo.mp3 Encrypted : False EncryptionMethod : Extension : mp3 FileName : demo FileSize : 18 FileType : MP3 Format Sound FSCreationClassName : Win32_FileSystem FSName : NTFS Hidden : False InUseCount : LastAccessed : 1/15/2015 8:47:16 AM LastModified : 1/15/2015 8:47:26 AM Path : workab Readable : True System : False Writeable : True Manufacturer : Version : PSComputerName : WIN81-ENT-01 CimClass : root/cimv2:CIM_DataFile CimInstanceProperties : {Caption, Description, InstallDate, Name...} CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
Let’s start by querying locally, again looking for folders that contain MP3 files under C:work. Here’s my query.
Get-CimInstance CIM_DataFile -filter "Drive='c:' AND path Like '\work\%' AND extension='mp3'" -OutVariable m
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.
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.
Get-CimInstance CIM_DataFile -filter "Drive='c:' AND path Like '\work\%' AND extension='mp3'" -OutVariable m | Get-CimAssociatedInstance -ResultClassName Win32_Directory | Select Name
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.
Get-CimInstance CIM_DataFile -filter "Drive='c:' AND path Like '\work\%' AND extension='mp3'" | Get-CimAssociatedInstance -ResultClassName Win32_Directory | Select Name -Unique | Sort
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.
I want to search for ZIP files under C:Work on CHI-CORE01 and get the matching folder paths.
Get-CimInstance CIM_DataFile -filter "Drive='c:' AND path Like '\work\%' AND extension='zip'" -computername chi-core01 |
Get-CimAssociatedInstance -ResultClassName Win32_Directory | Select Name,PSComputername -Unique | Sort Name
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.
Get-CimInstance CIM_DataFile -filter "Drive='c:' AND extension='zip'" -computername chi-core01 |
Get-CimAssociatedInstance -ResultClassName Win32_Directory | Select Name,PSComputername -Unique | Sort Name
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.
Get-CimInstance CIM_DataFile -filter "Drive='c:' AND extension='zip'" -computername chi-core01,chi-fp02 |
Get-CimAssociatedInstance -ResultClassName Win32_Directory | Select Name,PSComputername -Unique |
Sort Name | out-gridview -title "Zip Files"
In this article, I have been using the CIM cmdlets, which assumes you are running PowerShell 3.0 or later locally and remotely.
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.
Get-WMIObject CIM_DataFile -filter "Drive='c:' AND extension='zip'" -computername chi-core01 |
foreach { $_.GetRelated("Win32_Directory")} | Select Name,PSComputername -Unique | Sort Name
The result is the same WMI information.
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.