Can someone please help me with the following query.
I want to find the most efficient way of querying file names on a remote server where PowerShell is not installed by default on the remote Server (e.g. 2003 Server)
Now, thus far, as far as I am aware my options are
WMI CIM_DataFile
.NET [System.IO.Directory]::GetFiles(‘C:\Server1\c$’)
CmdLet Get-ChildItem
Now the thing is I want to limit how many levels the search goes down the directory structure for example:
C:\
C:\Temp
C:\Temp\Temp2
I just want to search in save C:\ and C:\Temp but not C:\Temp\Temp2
The .NET method above appears to be the fastest however to only option if has is AllDirectories e.g.
[System.IO.Directory]::GetFiles(‘C:\Server1\c$’,’*.bat’,’ALLDIRECTORIES’)
It does not have an up to 5 directories deep option for example, neither does WMI, so I have filter like this
Get-WmiObject -query “select * from win32_datafile where not (path like ‘\\%\\%\\%’)”
This is OK but again can be a bit slow
I wrote the following using the third option e.g. get-childitem, which works OK i.e. set the depth level with respect from the \ down e.g. 1 being root and 2 being c:\temp\ for example.
However this works fast when searching say up to two possible 3 levels but slows right down, when going a bit deeper.
Therefore my questions is, can anyone think of a faster/more efficient way to achieve this goal e.g. if there a .net type I can use that does allow you to set how many levels deep you want to go?
Thanks all in advance
Ernie
[CmdLetBinding()]
param([int]$Depth= 2,[string]$Filter="*.cmd",[string]$SearchFor="SDCli")
$VerbosePreference="Continue"
cls
$outputfile=New-Item-ItemTypeFile-PathC:\Ernie\OutPutFile.log-Force
Write-Verbose"Checking for files which match the following name $Filter"
Write-Verbose"Results will be written to $($outputfile.fullname)"
Write-Verbose"Getting Server list"
#$Servers = ([DirectoryServices.DirectorySearcher]"(&(ObjectClass=Computer)(operatingsystem=Windows Server*))").FindAll()
$Depth+= 1
$Servers= ([DirectoryServices.DirectorySearcher]"(&(objectClass=Computer)(cn=bovnsv01))").findone()
Write-Verbose"Computers Collection contains $(($Servers).count) Servers"
foreach ($Serverin$Servers) {
Write-Verbose"Testing connection to computer $($Server.psbase.properties.cn)"
if (Test-Connection-ComputerName$Server.psbase.properties.cn-Quiet-Count 2-ErrorAction 0) {
Write-Verbose"Checking drives on Server $($Server.psbase.properties.cn)"
$LogicalDisks=Get-WmiObject`
-Query"select * from win32_logicaldisk where (DriveType = 3 AND (DeviceID = 'C:' OR DeviceID = 'D:' OR DeviceID = 'E:' OR DeviceID = 'F:'))"`
-ComputerName$Server.psbase.properties.cn-Amended -EA 0 |
select @{n='Server';e={$_.__Server}},@{n='Drive';e={$_.DeviceID}}
Write-Verbose"Found $(($LogicalDisks).count) local fixed disks"
Write-Verbose"Constructing UNC paths"
foreach ($Diskin$LogicalDisks) {
$DiskDrive=$Disk.Drive-replace":","$"
Write-Verbose"Disk Drive set to $DiskDrive"
1..$Depth |% {
[string]$Script:Path="\\"+$Disk.Server+"\"+$DiskDrive+ $('\*'*$_)
Write-Verbose"Checking for files using path $path"
$Files+=get-childitem-path$Path-Filter$Filter -EA 0 |where {-not$_.PsIsContainer}
}
}}}
if ($Files) {
foreach ($Filein$Files) {
if ($File-match"\w+") {
Write-Verbose"Checking contents of file $File"
$reader= [System.IO.File]::OpenText($File)
try {
while (!$Reader.EndOfStream) {
$line=$reader.ReadLine()
# process the line
if ($line-match$SearchFor) {
Add-Content-Value$File-Path$outputfile
"File $File contains $SearchFor" }
}
}
finally {
$reader.Close()
}
}}}else {Write-Verbose"No Files Found"}