Using Find My Files in Your App

The new indexing mode of called Find My Files Enhanced expands the number of locations where apps can use the indexer to search. Any app can issue a query against the search indexer for Find My Files locations and build a great search experience.

 What is Find My Files

To understand why Find My Files is interesting you must understand the basics of how the indexer has worked since the beginning of time - defined here not as 1970 but the much more recent XP SP2 release

When the indexer sees a new file on the disk it does two things:

  1. Get the metadata about the file from the file system and make it searchable (such as file name and ACLs)
  2. Extract data from the file and make it searchable (the full text of documents or emails, EXIF properties on images)

Historically, these two operations were linked together. First the metadata would be extracted, then the full content. However, getting content from the file is up to 100x slower than just getting the metadata from the file system. The filesystem (especially on NTFS) can almost instantly give you the metadata, whereas reading a file stream from disk, parsing it, pulling out all the text or metadata, and storing that in the index is a CPU and disk intensive process.

This means that although the indexer could have indexed an entire hard drive, the extra volume of indexing work would cause the machine to grind to a halt. Thus, users were stuck without fast search outside of their user profile.

For Find My Files steps 1 and 2 are separated. Files included under Find My Files locations, only their file system metadata will be indexed, and the file content will not be opened. This lets the indexer index more files and folders using fewer resources.

The trade-off though is clear. In locations where only the file system metadata is gathered, the indexer doesn’t have any data about the content of files. This means that many types of queries cannot be served such as sorting pictures by date taken or location.

There are now 3 types of locations on a computer with Find My Files enabled:

Type of Location Examples What is indexed?

Type of Location

C:\WindowsC:ProgramDataRemovable drivesTemporary file locations Nothing – all searches are handled by opening files at query time and walking through them
Find My Files Locations  C:\MyFolderD:\PicturesBackupC:\Users\Adam\MySpecialFolder Only file system metadata:File PathSystem.ItemNameDisplaySystem.FileExtensionSystem.KindSystem.DateCreatedSystem.DateModifiedSystem.Shell.SFGAOFlagsStringsSystem.Link.TargetParsingPath
Indexed Locations  C:\Users\Adam\PicturesC:\Users\Adam\Videos All metadata and content for the file

Using Find My Files In Your App

Adding search over a Find My Files location is almost identical to using Windows Search normally or like using any other OLE DB connector. The full documentation for Windows Search is here, or if you’re looking for a quick start Josh Twist has a great write up.

The only gotcha to be aware of is that in Find My File locations, only the file system metadata will be available.

Below is a simple app that just gets the first 5 files off the D: drive that start with img*. 

 static void Main(string[] args)
{
    string query = @"SELECT TOP 3 System.ItemNameDisplay, System.DateCreated
                    FROM SYSTEMINDEX
                    WHERE scope='file:D:/'
                    AND (CONTAINS(System.ItemNameDisplay, 'img*'))";
    using (OleDbConnection objConnection =
           new OleDbConnection
           ("Provider=Search.CollatorDSO;Extended Properties='Application=Windows';"))
    {
        objConnection.Open();
        OleDbCommand cmd = new OleDbCommand(query, objConnection);
        using (OleDbDataReader rdr = cmd.ExecuteReader())
        {
            for (int i = 0; i < rdr.FieldCount; i++)
            {                       
                Console.Write(rdr.GetName(i));
                Console.Write('\t');
            }
            while (rdr.Read())
            {
                Console.WriteLine();
                for (int i = 0; i < rdr.FieldCount; i++)
                {
                    Console.Write(rdr[i]);
                    Console.Write('\t');
                }
            }
            Console.ReadKey();
        }
    }
}

The output is:

  SYSTEM.ITEMNAMEDISPLAY SYSTEM.DATECREATED
 IMG_0002.JPG 5/4/2013 7:14:19 PM
 IMG_0005.JPG 5/4/2013 7:18:06 PM
 IMG_0038.JPG 5/5/2013 8:22:53 PM

And that is it. Seriously – with only 25 lines of code we can pull the same results from the indexer that are used in the system search experience for your own app. With Find My Files, this code is even more valuable as users can search more locations on their machine using the search indexer.

There are countless ways to get fancy here. RANK BY COERCION gives you pinpoint control over how results are ordered, or a simple ORDER BY clause can do simple ordering easily. There are also countless variations you can make to the WHERE clause to filter by file types or kind of file. This is all documented in the Window Search Developer Guide, along with more samples to inspire your coding.