Find Anything with Vista’s Windows Desktop Search

indows Desktop Search (WDS) 3.0, introduced with Windows Vista, gives your computer fast search capabilities, helping you find your documents, e-mail, music, photos, videos, and other items quickly. Microsoft implemented the search engine that powers WDS 3.0 as a Windows service that’s shared by applications such as Outlook 2007 and OneNote 2007 to index application content and deliver instant results. Because WDS performs file indexing operations only during your computer’s idle time, there’s no negative impact on the user experience. But the nicest feature for developers is that, in addition to out-of-the-box integration with Office 2007 applications, WDS 3.0 exposes a programmatic API through which you can fully and easily integrate your applications with WDS?meaning you can let WDS handle searching and indexing tasks for your application’s output as well as Office and standard file types.

Windows Desktop Search 3.0 is fully integrated everywhere in Windows Vista, including the Start Menu, Control Panel, and Explorer.

When you first install it, WDS builds an index of the file contents on your computer. Because it’s purely a background task, building the initial index can take several hours; but after the index is complete and available, you will get nearly instant results when you search for a file. Because of the pre-built index, WDS is not only faster than any previous Windows search feature, but also produces more precise search results. In addition to providing a very generic search capability that works for most common file formats, WDS also allows you to create your own plugins (through IFilters) that allow you to search previously unsearchable file content, such as PDF files or custom output formats from your applications.

Although WDS 3.0 only ships with Vista, it’s a separate component, so you can also use WDS with Windows XP and Windows Server 2003. See http://support.microsoft.com/kb/917013 for more information.

What You Need
  • Visual Studio 2005 Professional RTM
  • Microsoft Windows Vista
  • The Microsoft Windows Vista SDK.

Integration with Windows Desktop Search 3.0
Windows Desktop Search 3.0 is fully integrated everywhere in Windows Vista, including the Start Menu, Control Panel, and Explorer. The search experience is consistent no matter where users launch it from, because it’s built on top of a single indexing platform, and it uses a brand-new property system. And because of its programmatic API, you can integrate your own programs with WDS seamlessly. There are two ways you can accomplish this:

  • OLE DB Provider for WDS?Works with WDS using the standard ADO.NET OLE DB classes
  • ISearchQueryHelper?An unmanaged COM interface you can access from .NET through a runtime callable wrapper (also known as Interop assembly) generated through Type Library Import Utility

I’ll walk you through an example of using each interface; then you can choose which you prefer.

Using the OLE DB Provider
To start, create a new Windows Forms project named SearchExample, add a button, a text box and a list box to the newly created form, and name them btnExecuteQuery, txtInput and lstResults respectively. After that, modify the form code to look like Listing 1, which starts by defining a helper method named ExecuteReader() that accepts a SQL query as an argument and returns the results in the form of an OleDbDataReader object. The ExecuteReader() method first retrieves the OLE DB search provider connection string from the app.config file.

      string connectionString = System.Configuration.      ConfigurationManager.AppSettings["WDSConnectionString"];

That connection string is defined in the section of the app.config file as follows:

           

Because search operations are read-only, the search OLE DB provider supports only SELECT statements.

Next, ExecuteReader() creates an instance of the OleDbConnection object, passing the connection string to its constructor, then opens the connection using the Open() method:

   _connection = new OleDbConnection(connectionString);   _connection.Open();   

After that it creates an instance of the OleDbCommand object, and sets its various properties to the appropriate values:

   OleDbCommand command = new OleDbCommand();   command.Connection = _connection;   command.CommandText = query;               

Finally, it executes the query by invoking the OleDbCommand.ExecuteReader() method and returns the results back to the caller:

   OleDbDataReader reader = command.ExecuteReader();   return reader;

As you can see from the ExecuteReader() implementation, the ADO.NET code required to perform search is exactly the same as executing a query against a data source. However if you look at the button-click code in Listing 1, you’ll see that the query passed as an input parameter to ExecuteReader() differentiates this search query from a traditional SQL query.

I’ll examine the search query format in depth. The button’s Click event concatenates the query:

   private void btnExecuteQuery_Click(object sender, EventArgs e)   {                  string query = string.Format(         "SELECT System.ItemNameDisplay, System.ItemType FROM " +         " systemindex WHERE CONTAINS("System.FileName", " +         " '"*{0}*"')", txtInput.Text);

The preceding query searches the System.FileName property for a match to the text entered by a user in the TextBox and return the values of the System.ItemNameDisplay and System.ItemType properties. The syntax of the query is as follows:

      SELECT        FROM [machineName.]SYSTEMINDEX       [WHERE ]

Here’s a more detailed explanation of each of the query components.

  • SELECT ?Represents a list of one or more comma-separated properties defined in the Windows Vista property system. Note that the familiar SELECT * syntax is not supported, which means you must explicitly list the names of the properties you want to search. For a complete listing of the properties supported by Windows Vista, refer to the documentation. In this example, the “Core” category contains the properties you need. The documentation describes System.ItemNameDisplay as “the unique representation of the item name most appropriate for end users” and System.ItemType as “the canonical type of the item […] intended to be programmatically parsed.”
  • FROM [machineName.]SYSTEMINDEX?Here you specify “SYSTEMINDEX,” which is the only local catalog you can query. However you also have the option of querying a remote catalog if the remote computer has the required software and configuration settings.
  • WHERE ?The WHERE clause supports the following predicates:
    • Simple predicates: LIKE and literal value comparisons (<,>,=)
    • Full-text predicates: CONTAINS and FREETEXT
    • Search depth predicates: SCOPE and DIRECTORY
The example query uses the CONTAINS predicate in the query to search for all the files where the filename contains a match to the input entered by the user.

Listing 1 supplies the completed query as an argument to the ExecuteReader() helper method and assigns the results returned from the ExecuteReader() method to a local variable:

      OleDbDataReader reader = ExecuteReader(query);      lstResults.Items.Clear();
 
Figure 1. OLE DB Search Provider Output: Running the search fills the list box with the values of the System.ItemNameDisplay and System.ItemType properties.

To display the data, you loop through the OleDbDataReader object and display the values of the first two columns:

      while (reader.Read())      {         lstResults.Items.Add(reader.GetString(0)         +  ".........." +          reader.GetString(1).ToString());      }   

Finally, close the OleDbDataReader object using the Close() method:

      reader.Close();              }

When you run the query, you’ll see generated output that looks similar to Figure 1.

Using the COM Interface
In addition to querying WDS through OLE DB Provider, you can also use an unmanaged COM interface to interact with WDS API. I’ll show you an example that uses the COM component to convert an Advanced Query Syntax (AQS) query to a SQL query that can then be sent to the ExecuteReader() helper method.

AQS is a commonly-used query syntax that lets end-users define targeted search queries. It’s supported in a number of Microsoft products, including Windows Vista, Outlook 2007, and Windows Desktop Search. AQS syntax is very similar to SharePoint’s search syntax, if you’re familiar with that. Here’s an example AQS search query that returns all files authored by “Thiru” that include the word “Longhorn.”

   Longhorn author:Thiru kind:everything store:files

For details on AQS, refer to the MSDN documentation.

Translating AQS to WDS
Because Windows supports AQS-based searches in so many places, it would be handy to provide users with the ability to search using AQS?meaning you need to convert the AQS query to a SQL query before sending it to the OLE DB search provider. Fortunately much of the work is built into the API already via the ISearchQueryHelper interface defined in the SearchAPI.tlb type library. This interface has a method called GenerateSQLFromUserQuery that converts an AQS query to a SQL query appropriate for the WDS OLE DB Provider.

Here are the steps to use the ISearchQueryHelper interface methods from within a Windows Forms application:

  1. Create the interop assembly by importing the SearchAPI.tlb type library (located in the Lib folder of the Windows Vista SDK) using the type library import utility (tlbimp.exe)
  2. Reference the managed assembly created in step 1 from within your .NET application
  3. Import the namespace and start writing code against the various classes

To create the interop assembly, open up the Windows SDK command prompt and enter the following command on a single line:

   tlbimp "C:Program FilesMicrosoft       SDKsWindowsv6.0LibSearchAPI.tlb"        /out:"C:WDSManaged.dll"

After referencing the resulting assembly from your project, import the namespace at the top of the form as follows:

   using WDSManaged;   

Now, add a button named btnConvertAQS to the default Windows form from the previous project, and modify its Click event as follows:

   private void btnConvertAQS_Click(object sender, EventArgs e)   {      CSearchManager manager = new CSearchManagerClass();      CSearchCatalogManager catalogManager =          manager.GetCatalog("SystemIndex");      CSearchQueryHelper queryHelper =          catalogManager.GetQueryHelper();                  string query =          queryHelper.GenerateSQLFromUserQuery(txtInput.Text);      OleDbDataReader reader = ExecuteReader(query);      lstResults.Items.Clear();      while (reader.Read())      {         lstResults.Items.Add(reader.GetString(0));      }      reader.Close();              }   

The preceding code starts by creating an instance of the search manager:

     CSearchManager manager = new CSearchManagerClass();   

Through the search manager class, you can get a reference to the SystemIndex catalog by calling the GetCatalog() method:

     CSearchCatalogManager catalogManager =        manager.GetCatalog("SystemIndex");   

Using the catalog manager instance, you can then get a reference to the query helper class that exposes a helper method named GenerateSQLFromUserQuery() to convert an AQS query to a SQL query:

        CSearchQueryHelper queryHelper =        catalogManager.GetQueryHelper();                 string query =        queryHelper.GenerateSQLFromUserQuery(txtInput.Text);   
 
Figure 2. WDS Search API Output: Here’s the search results after converting the user-entered AQS Query into SQL.

With that SQL query in hand, you can then execute the query and display the results in the list box using the code described in the previous section:

     OleDbDataReader reader = ExecuteReader(query);     lstResults.Items.Clear();     while (reader.Read())     {        lstResults.Items.Add(reader.GetString(0));     }

Figure 2 shows the sample output generated by the form.

In this article, you saw two ways using to interact programmatically with WDS 3.0 from within your .NET applications. You also had a brief look at the new OLE DB Search Provider introduced with WDS and the steps involved in executing queries through this new provider. Finally, you saw how to translate an AQS query to a SQL query that witll execute through WDS.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: