-
-
Save arebee/1928da03047aee4167fabee0f501c72d to your computer and use it in GitHub Desktop.
function Search-FileIndex { | |
<# | |
.PARAMETER Path | |
Absoloute or relative path. Has to be in the Search Index for results to be presented. | |
.PARAMETER Pattern | |
File name or pattern to search for. Defaults to *.*. Aliased to Filter to ergonomically match Get-ChildItem. | |
.PARAMETER Text | |
Free text to search for in the files defined by the pattern. | |
.PARAMETER Recurse | |
Add the parameter to perform a recursive search. Default is false. | |
.PARAMETER AsFSInfo | |
Add the parameter to return System.IO.FileSystemInfo objects instead of String objects. | |
.SYNOPSIS | |
Uses the Windows Search index to search for files. | |
.DESCRIPTION | |
Uses the Windows Search index to search for files. SQL Syntax documented at https://msdn.microsoft.com/en-us/library/windows/desktop/bb231256(v=vs.85).aspx Based on https://blogs.msdn.microsoft.com/mediaandmicrocode/2008/07/13/microcode-windows-powershell-windows-desktop-search-problem-solving/ | |
.OUTPUTS | |
By default one string per file found with full path. | |
If the AsFSInfo switch is set, one System.IO.FileSystemInfo object per file found is returned. | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(ValueFromPipeline = $true)] | |
[string]$Path, | |
[Parameter(Mandatory=$false,ParameterSetName="FullText")] | |
[Parameter(Mandatory=$false)] | |
[alias("Filter")] | |
[string]$Pattern = "*.*", | |
[Parameter(Mandatory=$false,ParameterSetName="FullText")] | |
[string]$Text = $null, | |
[Parameter(Mandatory=$false)] | |
[switch]$Recurse = $false, | |
[Parameter(Mandatory=$false)] | |
[switch]$AsFSInfo = $false | |
) | |
if($Path -eq ""){ | |
$Path = $PWD; | |
} | |
$path = (Resolve-Path -Path $path).Path | |
$pattern = $pattern -replace "\*", "%" | |
$path = $path.Replace('\','/') | |
if ((Test-Path -Path Variable:fsSearchCon) -eq $false) | |
{ | |
$global:fsSearchCon = New-Object -ComObject ADODB.Connection | |
$global:fsSearchRs = New-Object -ComObject ADODB.Recordset | |
} | |
$fsSearchCon.Open("Provider=Search.CollatorDSO;Extended Properties='Application=Windows';") | |
[string]$queryString = "SELECT System.ItemPathDisplay FROM SYSTEMINDEX WHERE System.FileName LIKE '" + $pattern + "' " | |
if ([System.String]::IsNullOrEmpty($Text) -eq $false){ | |
$queryString += "AND FREETEXT('" + $Text + "') " | |
} | |
if ($Recurse){ | |
$queryString += "AND SCOPE='file:" + $path + "' ORDER BY System.ItemPathDisplay" | |
} | |
else { | |
$queryString += "AND DIRECTORY='file:" + $path + "' ORDER BY System.ItemPathDisplay" | |
} | |
$fsSearchRs.Open($queryString, $fsSearchCon) | |
# return | |
While(-Not $fsSearchRs.EOF){ | |
if ($AsFSInfo){ | |
# Return a FileSystemInfo object | |
[System.IO.FileSystemInfo]$(Get-Item -LiteralPath ($fsSearchRs.Fields.Item("System.ItemPathDisplay").Value) -Force) | |
} | |
else { | |
$fsSearchRs.Fields.Item("System.ItemPathDisplay").Value | |
} | |
$fsSearchRs.MoveNext() | |
} | |
$fsSearchRs.Close() | |
$fsSearchCon.Close() | |
} |
I had to make the following changes to make it work:
- Rename the function as
searchFileIndex
: It seems that function names starting with a capital letter are not valid in powershell. I also removed the dash character, just in case special characters are not allowed either. - Call the function at the end of the script forwarding the script arguments as parameters:
searchFileIndex @args
All parameters are optional, but this would be an example of calling the script:
SearchFileIndex.ps1 -Path Documentation -Pattern *.pdf -Text "Next release" -Recursive
There's nothing needed to make this work as it stands @alvalea. This is a PowerShell Function. You can save the file (for example, as search-fileindex.ps1) then you can simply dot-source it and then use it in your other powershell scripts (or in your interactive session):
. c:\filepath\for\this\script\search-fileindex.ps1
then just invoke it like:
search-fileindex -path c:\here -pattern *.docx -recurse -text "Find this text"
I did add some parameters to set the connection and command timeouts to 0 so a long query didn't end with an error. If you want to do that, you can simply add these two lines prior to line 51 above (that opens the search connection)
$fsSearchCon.ConnectionTimeout=0
$fsSearchCon.CommandTimeout=0
On my Windows 11 22624.1391 system, certain search strings (the name of a specific super small scale product) would yield the following error:
{Application Error}
The exception %s (0x
At C:\Users\cpbot\OneDrive\configs\powershell\search-fileindex.ps1:76 char:9
+ $fsSearchRs.MoveNext()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Weirdly, for these strings, EOF
would only evaluate correctly the second time. In other words, if I did e.g. Write-Host $fsSearchRs.EOF
right before the while loop, it would correctly not enter. If I did not do that, it would enter, and then MoveNext
would fail.
Other gibberish strings that also yield no results do correctly evaluate. This is currently reproducible.
To work around this, I changed the while loop to the following, so that it just gracefully yields no results:
While(-Not $fsSearchRs.EOF -and $fsSearchRs.Fields.Item("System.ItemPathDisplay").Value){
In this strange state, $fsSearchRs evals to the following on first eval:
Properties : System.__ComObject
AbsolutePosition :
ActiveConnection : System.__ComObject
BOF : True
Bookmark :
CacheSize : 1
CursorType : 0
EOF : True
Fields : System.__ComObject
LockType : 1
MaxRecords : 0
RecordCount : -1
Source : SELECT System.ItemPathDisplay FROM SYSTEMINDEX WHERE System.FileName LIKE '%.%' AND FREETEXT('telesensi') AND SCOPE='file:C:/users/cpbot/OneDrive' ORDER BY System.ItemPathDisplay
AbsolutePage : -1
EditMode : 0
Filter : 0
PageCount : -1
PageSize : 10
Sort :
Status :
State : 1
CursorLocation : 2
MarshalOptions : 0
DataSource : System.__ComObject
ActiveCommand : System.__ComObject
StayInSync : True
DataMember :
Index :
I'm leaving this here in case anyone else runs into similar issues.
please share sample parameters to check the functionality