Desktop search tools from Google and Microsoft allow us to use the same
instant search paradigm on our desktop machines as the ones within our files,
e-mail, pictures and more. Now, Windows Vista comes with a built-in search tool
that indexes the content in the background so that you can get instant search
results. The content, that is indexed, can be from within recognized file types,
file properties, e-mail, images, music, videos, etc.
The best part is that the search is also available as an API that you can
code against. So if you're developing applications for Windows Vista (and for
Win XP/2003 as well, since the search API will be back-ported to them as well),
you can incorporate instant search within your application-without much work.
Note that if your application has its own special file type, you can even get
the Windows Vista search to index
content within these types too by writing special filters for content and
property descriptors. However, this is outside the scope of this article. Here
we will look at quickly incorporating search functionality into an existing .NET
application using the Vista engine.
|
For the purpose of this article, we have a simple .NET Windows Forms
application that has some dummy controls like a Calendar and a
RichTextBox that is supposed to be the main part of the application. Of course,
they do nothing. We also have a search text box, a button to perform the search,
a list box to display the results and buttons for filtering out only e-mail,
images or files.
Before we look at the code, there are some concepts for using the search API
of Vista that you should be aware of.
- The API is given to you as an OLEDB provider. That is, you can use your
database programming in .NET to query the search index. - The Select statement used to query the index is slightly different than
what you use against databases. We'll discuss this in detail, in this
article.
As a sample application, let's write event handlers for each of the
different buttons used for searching like this.
private void btnAll_Click(object sender,
EventArgs e)
{
GetSearchResults("");
}
private void btnEmail_Click(object sender,
EventArgs e)
{
GetSearchResults("EMAIL");
}
private void btnImages_Click(object sender,
EventArgs e)
{
GetSearchResults("IMAGES");
}
private void btnFiles_Click(object sender,
EventArgs e)
{
GetSearchResults("FILES");
}
The search API allows you to search all through the index or filter out, based on type (such as emails) or location (such as a particular folder) |
These functions call a standard search function for all items, e-mail, images
or files. We will now write the actual search code in this function.
private void GetSearchResults(String Type)
{
// Get the keywords entered
String KeyWords = txtSearch.Text;
// OLEDB Provider for Vista Search connection string
String indexerConnString = "provider=Search.CollatorDSO.1;
EXTENDED PROPERTIES=\"Application=Windows\"";
// Actual SQL
String strSQL = "";
// For storing results
List
using (OleDbConnection conn = new
OleDbConnection(indexerConnString))
{
conn.Open();
// Create a new SQL query for the keywords
strSQL = "select System.Title, System.Size, System.Search.Rank, System.Kind
from SYSTEMINDEX..SCOPE() where FREETEXT(*, '" + KeyWords + "')
";
switch (Type)
{
case "":
strSQL += "order by System.Kind"; break;
case "EMAIL":
strSQL += "AND SCOPE='mapi:/' order by System.Kind"; // Get only
emails
break;
case "IMAGES":
strSQL += "AND SCOPE='file:C:/Users/Vinod/Documents' AND
FREETEXT('Sytem.CanonicalType', 'JPG') "; // Get only JPGs
break;
case "FILES":
strSQL += "AND SCOPE='file:C:/Users/Vinod/Documents' order by System.Kind";
// Search only in My Docs
break;}
OleDbCommand cmd = new OleDbCommand(strSQL, conn);
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{ // Get the results into list
Results.Add(String.Format("{0} ({1} bytes)", reader.GetString(0),
reader.GetValue(1)));
}
}
// Show results in ListBox
lstResults.DataSource = Results;
}
}
While this code does simple things, there are a few things you should note.
Note that the connection string used is the one that is required to work with
the Vista Search Indexer. Also the Select statement has the following points of
interest.
You can select from any system property such as System.Title, System.Size and
System.Kind. Vista defines a huge number of such properties for different
objects. For instance, images will have properties like System.Photo.CameraModel,
music files will have System.Album. TrackNo or System.Album.Artist, etc. You can
query all these properties as if they are fields in a database table.
The FROM clause will always be SYSTEMINDEX..SCOPE() as this is where it
searches the index from.
The FREETEXT clause allows you to search within content, a property or both
for a particular value. In the case above, by putting a “*”, we search in
both content and properties of files for the keywords.
The SCOPE clause allows restricting the search to different areas of the
index. For instance, when wanting to search within e-mail only, we give the
parameter as mapi:; for searching in a particular folder only, the parameter
becomes file:
slashes as in UNIX.
Also note that the code returns the corresponding values within the list box.
However, neither there's any error handling code in this sample, nor is there
any message returned when there are no results.
The Vista search-indexing feature lets you add search functionality and
search filtering into any application. A look at the system properties for
different objects lets you display more information about all the objects
available. And now a user doesn't have to switch out of your application to
find information that he is looking for.