How to use the Windows Search Index from PowerShell

How to use the Windows Search Index from PowerShell

Full-text searches offer a fast and efficient way to retrieve relevant information from a vast array of files and documents on your Windows computer

Windows Index Search, also known as Windows Search or Windows Indexing, is a feature in the Microsoft Windows operating system that improves the speed and efficiency of file searches on your computer. It is designed to create and maintain an index of the files and folders stored on your local drives, allowing for faster and more accurate searches.

When you perform a search using Windows Index Search, the system does not have to scan every file and folder on your computer every time you search. Instead, it refers to the index, which is a database containing information about the files' names, locations, and contents. This significantly reduces the time it takes to find and retrieve search results, especially when dealing with a large number of files.

Key Features and Benefits of Windows Index Search:

  • Fast Search Results: With the index pre-built, Windows Search can quickly return search results, making it easier to find the files and documents you need.

  • Support for Various File Types: Windows Index Search supports various file types, including documents, images, music, videos, and more.

  • Partial and Phrasal Search: It allows partial word matches and supports searching for phrases, making it more flexible and powerful.

  • Outlook Integration: The Windows Search index can also be used by Microsoft Outlook to speed up email searches.

  • Customization: Users can customize which folders and locations are indexed to include or exclude specific locations based on their preferences.

  • Advanced Search Operators: Windows Search supports advanced search operators, such as AND, OR, and NOT, to refine search queries further.

  • Real-Time Indexing: As files and folders change or new ones are added, the index is updated in real-time to ensure the search results remain up-to-date.

How to set the index sources

The Windows Index Search can look for text in multiple locations. You can specify the folders that you want to add to the database. To edit the directories included in the index you have to do the following steps:

  • Win + S: press the "Windows key" plus the "key s" to open the Windows Search panel

  • Type Indexing Options to open the corresponding dialog

Windows Search pop-up

  • Add the folders that you want to include in the index

Once you have configured the folders to be included in the database, the Index Engine will start indexing all the documents included in those locations. Once it finishes, it will show a message saying that the indexing process is complete. From then on, you can do full-text searches on the specified directories.

How to do full-text searches on the Windows Explorer

The Windows Explorer provides you with a search text box that allows you to look for files or directories. To do a full-text search using Windows Explorer you have to do the following steps:

  • Open the Windows Explorer window

  • Navigate to the folder where you want to perform the search

  • Type in the search text box the term that you are looking for, specifying the content filter (e.g.: content: "design analysis")

As the contents of all the documents contained in that folder have been already indexed by the Windows Search Index, you will see how the results of documents containing that term (if any) start to emerge immediately.

How to do full-text searches on PowerShell

We are now going to see how we can use that functionality from a PowerShell script. It will use the APIs exposed by Windows to have access to the Windows Search Index database.

function SearchIndex {
<#
.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 (  
        [string]$Path = $PWD,
        [string]$Pattern = "*.*",
        [string]$Text = $null,
        [switch]$Recurse = $true,
        [switch]$AsFSInfo = $false
    )

    $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 System.Search.Contents='" + $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)

    While(-Not $fsSearchRs.EOF){
        if ($AsFSInfo){
            [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()
}

SearchIndex @args

You can copy this script to a file named SearchIndex.ps1. As long as it is contained in one of the directories defined in the Path environment variable, you will be able to run it from any location on the PowerShell terminal. The script supports several arguments. It looks recursively in the folders contained in the current directory by default. It looks over all kinds of documents by default too. But the argument -Pattern allows you to filter out the results just to the files of the specified extension.

PS C:\>SearchIndex.ps1 -Text 'design analysis' -Pattern '*.pdf'

How to do full-text searches from the Windows run dialog

Windows has a very useful feature that allows you to quickly execute a command. To do so, you just have to press the "Windows key" plus the "key r", and you will see a pop-up dialog called Run. You can type there any program that is available on the Path environment variable, and execute it.

In our case, we want to trigger the execution of a full-text search over any document contained in the Windows Search Index database from that Run dialog. That way, we would just need to type "Win + r" and the search command together with the search term to do a full-text search over all the target documents on our machine. Not bad, right?

The problem is that this Run dialog can only run batch files, not PowerShell scripts. Therefore, to overcome that limitation, we have to create a wrapper batch file that will call our PowerShell script. And add the location of this wrapper batch file to our Path environment variable.

We are going to create a search-text.bat file, that will allow us to perform a full-text search over any pdf file contained in a specific directory, which belongs to the Windows Search Index database.

@echo off

Rem Description: Search text in Windows Search Index pdf files
Rem Usage: search-text.bat {strings}
Rem Example: search-text.bat Seamless

set cmd="SearchIndex.ps1 -Path 'C:\Users\alem\Documents' -Pattern *.pdf -Text '%*' -Recurse"
echo %cmd%

PowerShell -ExecutionPolicy Bypass -Command %cmd%
Pause

Once we have done that, we can use the Run dialog to execute the SearchIndex script to search for all the PDF documents from that directory that have been indexed in the Windows Search Index database.

Run dialog

And that's all. With this utility, you can search for any text at lightning speed on your computer. It is so fast, that it almost feels like you have a Google Search Engine on your local laptop.