0

I want to be able to query a remote windows desktop for a particular file however I have the following constraints:

  1. I cannot make the assumption that powershell remoting is enabled.
  2. I don't know the exact location of the file
  3. Time is a factor

This has led me to the following query: SELECT * FROM CIM_DataFile WHERE Drive ='C:'AND FileName='Fake' AND Extension='dll'

This takes a relatively long time in comparison to something like Get-childitem in powershell which allows me to refine my search by folders and subfolders.

I could always do something like: SELECT * FROM CIM_DataFile WHERE Drive ='C:'AND FileName='Fake' AND Extension='dll' AND Path like '\\Windows\\System32\\%' however this query increases the load on the remote and doesn't actually take any less time.

Is there any way I can use WMI to do some type of recursive search?

user2228313
  • 119
  • 1
  • 3
  • 11
  • `Get-CimInstance Win32_Directory -Filter "Name = 'C:\\Windows\\System32'" |Get-CimAssociatedInstance -Association Win32_Subdirectory` – Mathias R. Jessen Aug 16 '18 at 21:19
  • You don't say what OS and PS version (source and target). There are cmdlets one can use without PSRemoting enabled. https://technet.microsoft.com/en-us/library/ff699046.aspx or the Mathias touted route. – postanote Aug 16 '18 at 21:35

1 Answers1

0

If you don't have PowerShell remoting enabled on the target machine you'll have to use DCOM to connect to WMI. DCOM connectivity is turned off by default on modern windows systems so you'll have to enable it - in which case you'd be better off enabling PowerShell remoting.

If you have to use WMI you'll need something like this

function get-wmifile {
[CmdletBinding()]
param (
 [Parameter(Mandatory = $true)]
 [string]$path,
 [string]$file
)

if ($path.IndexOf('\\') -le 0 ){
  $path = $path.replace('\', '\\')
}

if ($path.IndexOf('*') -ge 0 ){
  $path = $path.replace('*', '%')
}

Write-Verbose -Message "Path to search: $path"

$folders = Get-CimInstance -ClassName Win32_Directory -Filter "Name LIKE '$path'" 
foreach ($folder in $folders){
 if ($file) {
   Get-CimAssociatedInstance -InputObject $folder -ResultClassName CIM_DataFile |
   where Name -Like "*$file" |
   Select Name
 }
 else {
   Get-CimAssociatedInstance -InputObject $folder -ResultClassName CIM_DataFile |
   Select Name
 }
}

}

Use the function as

PS> get-wmifile -path 'c:\test*'

Name                              
----                              
c:\test\counters.csv              
c:\test\p1.txt                    
c:\test\test.md                   
c:\test2\p1.txt                   
c:\test2\test3\p2.txt             
c:\testscripts\eventlogchanges.txt
c:\testscripts\tempfolderlog.csv  
c:\testscripts\test.ps1       

or to find a file

PS> get-wmifile -path 'c:\test*' -file 'p1.txt'

Name           
----           
c:\test\p1.txt 
c:\test2\p1.txt

As you say using Get-ChildItem would be much quicker than WMI. There isn't a way to speed up the WMI - accessing file data is slow - so my recommendation is to stick with get-ChildItem