Tome's Land of IT

IT Notes from the Powertoe – Tome Tanasovski

Powershell Tackles Windows Desktop Search

A great question was posed in the Microsoft Powershell forum,

“In PowerShell, which command should I use to know the directories currently included and excluded from the indexed system of Windows 7?”

I thought to myself that this was an interesting question, and one that couldn’t be more relevant.  I’ve recently been tackling the realities of virtualizing Windows 7 enterprise-wide.  While the most important goal is to attempt to create a stateless and OS independent application experience the reality of desktop virtualization is storage IO reduction in order to achieve the kind of density that makes it worthwhile.  There are a few articles that talk about the methods to tune the Windows 7 build to ensure a better virtual experience.  Without digressing down that road (perhaps another day) I would like to mention that one of the tweaks is to remove WDS (Windows Desktop Search) services or indexes.  While I’m still unsure exactly what is going to be needed or what is best-practice around this topic I quickly realized that being able to manage the components of WDS with Powershell could be important very soon.  It can be used as a utility to monitor configuration, deploy configuration changes, or rebuild the index.

I was surprised to find that this topic seems to be virgin ground in the Powershell community, but I enjoyed the opportunity to do some detective work.  The first thing you’re going to need is to download the Interop dll from Microsoft.  This can be found in the Windows Search SDK (which is a self-extracting zip file that only has 600K in it).  Once you have it extracted you need to load up Powershell with elevated UAC credentials.

Below is the script that shows how to load the assembly, create the necessary objects, and enumerate through the list of scope rules on the SystemIndex.  This will show a list of all patterns that are included or excluded from the index:

#Load the dll
Add-Type -path "Microsoft.Search.Interop.dll"
#Create an instance of CSearchManagerClass
$sm = New-Object Microsoft.Search.Interop.CSearchManagerClass 
#Next we connect to the SystemIndex catalog
$catalog = $sm.GetCatalog("SystemIndex")
#Get the interface to the scope rule manager
$crawlman = $catalog.GetCrawlScopeManager()

#Next we set some variables to use in the enumeration
$scopes = @() #The array that will hold our scopes
$begin=$true #A variable to test for the first run of the enumeration
[Microsoft.Search.Interop.CSearchScopeRule]$scope = $null #This will be passed 
                                   #as a reference to the enumeration process.
                                   #It will hold the scope as we enumerate.

#Grab the enumeration object from the Crawl Scope Manager
$enum = $crawlman.EnumerateScopeRules() 
while ($scope -ne $null -or $begin) {
     #To traverse the collection you must use the Next method
     $enum.Next(1,[ref]$scope,[ref]$null)
     $begin = $false
     $scopes += $scope #populate our array so we can use it later Powershell style
}
$scopes|ogv #Inspect what the scopes look like

The pattern or url is fairly self explanatory.  It’s nice to note that you can include wildcards anywhere in the string.  If IsIncluded is 1 the path is a part of the WDS indexing process.  If it is set to 0 it means that the path is explicitly excluded from indexing.

In order to add or remove patterns to the list you use the CSearchCrawlScopeManagerClass object you created.  Use AddUserScopeRule or RemoveScopeRule to modify the list.  You also must call the SaveAll method when you are done.

Let’s add c:\windows\addins\* to the list:

$crawlman.AddUserScopeRule("file:///c:\windows\addins\*",$true,$false,$null)
$crawlman.SaveAll()

To remove what we just added you do the following:

$crawlman.RemoveScopeRule("file:///c:\windows\addins\*")
$crawlman.SaveAll()

To explore the rest of the functions and options available you should read through the Windows Search Developer’s Guide as well as the MSDN reference documentation.  Besides the concept of Scopes it’s important to be aware of roots if you plan on adding something new to the list i.e. a new drive or provider.  It’s also important to note that when you search the Internet for C# code samples on this subject you will find that they use type names and constructors that are unusable through Powershell.  The Powershell version of these classes contain the suffix Class i.e CSearchManagerClass instead of CSearchManager.  You can use a library browser to look at the dll to see the public classes with constructors if you need to.

Obviously, this is screaming to be wrapped into a nice Powershell friendly set of modules, and if no one beats me to it I will get to it eventually 🙂

Here’s the original thread that inspired this article.  It also follows my maddening search for answers.

Advertisements

One response to “Powershell Tackles Windows Desktop Search

  1. Pingback: Episode 116 – Master Debugger John Robbins « PowerScripting Podcast

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: