kamagra how much to take

Programmatically Using Windows Search Service 4 to Search Network Shares

Having had to search for this for hours, combine about 50 different approaches, I decided to write a small blog post on using Windows Search Service 4 in order to search remote shares. First question you probably have is, why the hell would I use Windows Search Servicewhen I can just use the SharePoint search?

There are a couple reasons.

First and foremost is the consideration that TDE (Transparent Data Encryption) might introduce unacceptable overhead for a 2010 environment that requires encryption for data-at-rest (all data in computer storage while excluding data that is traversing a network or temporarily residing in computer memory to be read or updated). While getting practical times related to performance stuff like this is dependent on several factors, you can expect between 3% to 30%, 3% being on the low end for low I/O Low Usage- High Performance scenarios and 30% for the other end of the spectrum.

Second is cost. An Enterprise license of SQL is not cheap. For one off applications where security is a concern this can be a deal breaker. Such applications generally mandate that a separate, orphaned database instance be used. Thus the cost incursion might be something that a company cannot absorb.

And there are other reasons…but I get diverted!

So if your documents are being indexed on a remote share the objects that are of most importance are:

CSearchManager – Provides methods for controlling the search service.
CSearchCatalogManager – it’s…you know the catalog manager.
CSearchQueryHelper – allows a conversion from Advanced Query Syntax (AQS) to a SQL query. So you aren’t pulling your hair out writing your multiple query types.

To query the data source, you are going to use:

OleDbConnection – provide a unique connection to the search data source
OleDbCommand – Represents a SQL statement to execute against a the search data source
OleDbDataReader – used to read the search data quickly

Alrighty, now let’s talk about how all these things are going to play together.

First thing is first, and you have to create an object that you can build a collection up of that you can hydrate with the properties that you are interested in. Something like:

  1. public class Result
  2. {
  3. public string FullPath { get; set; }
  4. public int Rank { get; set; }
  5. }

Nothing fancy about this, we are just creating a holding type to populate a strongly typed collection with our relevant return values so we can bind it to some display vehicle at some other point in the application. The reason that we need it is because it is going to be a part of our method return type. Since there is nothing fancy about the properties we just throw in auto-properties.

Now onto the searching part of the application, using those particular, aforementioned objects from before. The first thing to do is hydrate a reference to the search service instance by creating a new CSearchManager object, off of which a new CSearchCatalogManager can be spawned using the CSearchManager.GetCatalog method, which in turn points to the local SystemIndex. Using the new CSearchCatalogManager object the GetQueryHelper method can be invoked to create a new CSearchQueryHelper to start query specifications with its numerous properties. The CSearchQueryHelper.GenerateSQLFromUserQuery is awesome because you can simply pass in the string parameter that represents the content being searched, and then to grab the remote index we slightly modify the query content before using it.  

  1. queryHelper.QueryWhereRestrictions = string.Format("AND (\"SCOPE\" = 'file://{0}/{1}')", ServerName, Share);

and

  1. selectCommand = selectCommand.Replace("FROM \"SystemIndex\"", string.Format("FROM \"{0}\".\"SystemIndex\"", ServerName));
  1. private const string ServerName = "<Your Server Name>";
  2. private const string Share = "<Your Network Share Name>";
  3.  
  4. public List<Result> SearchFolder(string strContent)
  5. {
  6. var items = new List<Result>();
  7. if (string.IsNullOrEmpty(strContent))
  8. {
  9. return items;
  10. }
  11. var manager = new CSearchManager();
  12. CSearchCatalogManager catalogManager = manager.GetCatalog("SystemIndex");
  13.  
  14. CSearchQueryHelper queryHelper = catalogManager.GetQueryHelper();
  15. queryHelper.QueryContentLocale = 1033;
  16. queryHelper.QueryMaxResults = 100;
  17. queryHelper.QueryKeywordLocale = 1033;
  18. queryHelper.QuerySelectColumns = "System.ItemPathDisplay,System.Search.Rank,System.ItemNameDisplay";
  19. queryHelper.QueryWhereRestrictions = string.Format("AND (\"SCOPE\" = 'file://{0}/{1}')", ServerName, Share);
  20. queryHelper.QuerySorting = "System.ItemPathDisplay ASC ";
  21. queryHelper.QueryContentProperties = "System.Search.Contents,System.ItemNameDisplay";
  22.  
  23. string selectCommand = queryHelper.GenerateSQLFromUserQuery(strContent);
  24. selectCommand = selectCommand.Replace("FROM \"SystemIndex\"", string.Format("FROM \"{0}\".\"SystemIndex\"", ServerName));
  25. using (var conn = new OleDbConnection(queryHelper.ConnectionString))
  26. {
  27. conn.Open();
  28. using (var command = new OleDbCommand(selectCommand, conn))
  29. {
  30. using (OleDbDataReader wdsResults = command.ExecuteReader())
  31. {
  32. if (wdsResults != null)
  33. {
  34. while (wdsResults.Read())
  35. {
  36. var aResult = new SearchResultItem
  37. {
  38. FullPath = wdsResults.GetString(0),
  39. Rank = wdsResults.GetInt32(1),
  40. };
  41.  
  42. items.Add(aResult);
  43. }
  44. wdsResults.Close();
  45. }
  46. }
  47. }
  48. }
  49. return items;
  50. }

And that’s it! Hope I save someone some headaches!

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>