Prof. Powershell
Where Did I Put That File? Part 1
Jeffrey Hicks walks you through making your search query find exactly what you want to find.
- By Jeffery Hicks
- 04/02/2013
Finding files is very much like finding a needle in a haystack. Sometimes we're checking a file to verify its version against a known vulnerability. Or we simply want to verify a file exists. Of course, if you know the full path and file name, this is pretty simple. But what if the file could be in a different location? Maybe you need to find all instances of a file.
Using the Get-ChildItem cmdlet or its dir alias will work, although it can be time consuming and isn't the best choice if you want to search one or more remote computers. An alternative is to use WMI and the CIM_DATAFILE class. Searching for instances of this class can be tricky, especially if you don't have a lot of WMI experience.
Because you can be searching through thousands of files, the more specific you can make your query the better. For example, if you know the complete path to the file, query for it.
PS C:\> get-wmiobject cim_datafile -filter "Name='c:\\program files\\windows defender\\mpclient.dll'"g
Compressed : False
Encrypted : False
Size :
Hidden : False
Name : c:\program files\windows defender\mpclient.dll
Readable : True
System : False
Version : 4.0.9200.16384
Writeable : True
The \ in the path needs to be escaped with a second \ which is why the filter looks the way that it does. But this runs very quickly. Plus because this is WMI, you can query remote computers and use alternate credentials.
But, for situations where you don't know the full path you need to be a bit more creative. You also need to specify as many components of the file you seek as you can. For example, the default behavior is to search all drives, which you probably don't need. So build your query to at least include the drive, like C:. Here's my filter again, built with a bit more flexibility:
PS C:\> get-wmiobject cim_datafile -filter "filename='mpclient' AND extension='dll' AND drive='C:'"
This will take a bit longer to run, and will return all instances of a file called mpclient.dll, including any hidden versions. If you think it will take a while, especially if you are searching multiple computers, then run the command as a background job.
PS C:\> get-wmiobject cim_datafile -filter "filename='mpclient' AND extension='dll' AND drive='C:'"-comp computerA,computerB –asjob
If you are running PowerShell 3.0 you could also use Get-CimInstance.
PS C:\> get-ciminstance cim_datafile -filter "filename='mpclient' AND extension='dll' AND drive='C:'" -comp computerA,computerB
In fact, you could turn this into a simple function.
Function Get-CIMFile {
[cmdletbinding()]
Param(
[string]$file,
[string]$drive="C:",
[string[]]$Computername=$env:computername
)
Write-Verbose "Searching for $File on Drive $Drive"
#get the first part of the name
$filename = $file.split(".")[0]
#get the last part of the name
$extension=$file.Split(".")[1]
$filter = "Filename='$filename' AND extension='$extension' AND Drive='$drive'"
Get-WmiObject -Class CIM_Datafile -Filter $filter -ComputerName $Computername
}
In the next lesson, we'll continue looking at techniques for finding files with CIM_DATAFILE.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.