Click here to Skip to main content
15,892,005 members
Articles / Programming Languages / C#
Article

Administrate Indexing Server from within your application

Rate me:
Please Sign up or sign in to vote.
4.09/5 (5 votes)
1 Jul 20058 min read 39.5K   19   7
Describes in detail how you can programmatically administrate Indexing Server, for example create a new Indexing catalog and then add folders to be indexed by this catalog.

Introduction

You can leverage Microsoft Indexing Server to provide powerful search capabilities within your application. Indexing Server can be used to index files on your local or network file system as well as files of your local web site. You can then query the Indexing catalog using a standard SQL syntax. The following article describes in detail how you can create and configure your own Indexing catalog and then search it from within your application. This article concentrates on how you can programmatically administrate Indexing Server, for example create a new Indexing catalog and then add folders to be indexed by this catalog.

The Indexing Service administration API

Current versions of the .NET Framework do not provide any types to programmatically administrate the Indexing Server. But Indexing Server provides a COM based API that you can use. Add a reference to the “Indexing Service Administration Type Library 1.0” which you can find under the COM tab of the "Add Reference" dialog. This references the “ciodm.dll” in the windows\system32 folder. Next import the namespace “CIODMLib” which will give you access to the three types:

  • AdminIndexServerClass- This type is used to administrate the Indexing Server itself. It allows to create or remove catalogs, start or stop the Indexing service, etc.
  • CatAdmClass - This type provides access to an existing Indexing catalog. You can add or remove search scopes, start or stop the catalog, etc.
  • ScopeAdm - This type provides access to a search scope. You can set logon information for the scope, start a full or incremental scan, etc.

How to retrieve the list of Indexing catalogs?

Indexing Server can have many Indexing catalogs and your application always tells the Indexing Server which catalog to search for. You can use the AdminIndexServerClass type to enumerate all the defined Indexing catalogs. First you need to create an instance of the type AdminIndexServerClass. Then you can call FindFirstCatalog() to find the first catalog in the list. It returns true if it finds a catalog otherwise false. To find the next catalog you can call FindNextCatalog() which again returns true if it finds another catalog otherwise false. As the example below shows you first call FindFirstCatalog() and then in a loop FindNextCatalog() till one of them returns false. Each time you then call GetCatalog() to get a reference to the current catalog in the list. This returns an object of the type object and you need to query for the appropriate interface on that object. Simple type casting will not work as you are working with COM objects. You need to use the “as” keyword followed by the interface you are looking for. Underneath, this will query for the appropriate interface on that COM object and return null if not present or a reference to the interface. The interface you are looking for is the ICatAdm interface which provides you access to the catalog itself. The CatAdm type itself implements the ICatAdm interface.

C#
protected void FillCatalogList(ListView ListOfCatalogs)
{
    AdminIndexServerClass Admin = new AdminIndexServerClass();
    
    // remove any existing item in the catalog list
    ListOfCatalogs.Items.Clear();
    
    // finds the first catalog in the list
    bool FoundCatalog = Admin.FindFirstCatalog();
    
    // loop through all catalogs present
    while (FoundCatalog)
    {
        // gets the object representing the current catalog
        ICatAdm Catalog = Admin.GetCatalog() as ICatAdm;
        
        // adds the catalog details to the list view
        ListViewItem Item = 
               ListOfCatalogs.Items.Add(Catalog.CatalogName);
        Item.SubItems.Add(Catalog.CatalogLocation);
        Item.SubItems.Add(Catalog.IsUpToDate.ToString());
        Item.SubItems.Add(Catalog.DocumentsToFilter.ToString());
        Item.SubItems.Add(Catalog.FilteredDocumentCount.ToString());
        Item.SubItems.Add(Catalog.DelayedFilterCount.ToString());
        Item.SubItems.Add(Catalog.FreshTestCount.ToString());
        Item.SubItems.Add(Catalog.IndexSize.ToString());
        Item.SubItems.Add(Catalog.PctMergeComplete.ToString());
        Item.SubItems.Add(Catalog.PendingScanCount.ToString());
        Item.SubItems.Add(Catalog.PersistentIndexCount.ToString());
        Item.SubItems.Add(Catalog.QueryCount.ToString());
        Item.SubItems.Add(Catalog.StateInfo.ToString());
        Item.SubItems.Add(Catalog.TotalDocumentCount.ToString());
        Item.SubItems.Add(Catalog.UniqueKeyCount.ToString());
        Item.SubItems.Add(Catalog.WordListCount.ToString());
        
        // finds the next catalog in the list
        FoundCatalog = Admin.FindNextCatalog();
    }
    
    // select the first catalog in the list
    if (ListOfCatalogs.Items.Count > 0)
        ListOfCatalogs.SelectedIndices.Add(0);
}

As the example above shows the ICatAdm interface provides a number of properties about the catalog. You can obtain the name, the location, if the catalog is up to date or not, etc. The example above adds each found catalog to a list view.

How to start, stop, pause or continue Indexing Server?

The AdminIndexServerClass provides four methods to start, stop, pause and continue the Indexing service. It also provides methods to find out if the service is running or paused:

  • Start()- starts the Indexing service.
  • Stop()- stops the Indexing service.
  • Pause()- pauses the Indexing service.
  • Continue()- continues a paused Indexing service.
  • IsRunning()- returns true if the Indexing service is running.
  • IsPaused()- returns true if the Indexing service is paused.

How to add or remove an Indexing catalog?

You can add a new catalog with the method AddCatalog(). You need to pass along the name of the new catalog as well as the folder location where the catalog will be created. You need to restart the Indexing service before you can use a newly created catalog. The following example shows a dialog so the user can enter the name and location of a new catalog. Next it calls AddCatalog and then asks the user whether to restart the Indexing service so the catalog becomes usable. Finally it calls the method shown above to re-query the list of defined catalogs - FillCatalogList().

C#
private void AddCatalog_Click(object sender, EventArgs e)
{
    // the dialog to create a new catalog
    AddNewCatalog AddNew = new AddNewCatalog();
    
    // we want to create the catalog
    if (AddNew.ShowDialog(this) == DialogResult.OK)
    {
        AdminIndexServerClass Admin = 
                        new AdminIndexServerClass();
        
        // create the new catalog
        Admin.AddCatalog(AddNew.NewCatalogName, 
                         AddNew.NewCatalogLocation);
        
        // restart the service for the new catalog to function
        if (MessageBox.Show(this, RestartService, this.Text,
                  MessageBoxButtons.YesNo, 
                  MessageBoxIcon.Question) == DialogResult.Yes)
        {
            Admin.Stop();
            Admin.Start();
        }
        
        // refresh the list of catalogs
        FillCatalogList(ListOfCatalogs);
    }
}

You can call RemoveCatalog() to remove an existing catalog. You need to pass along the name of the catalog. You also need to first stop the Indexing service to be able to remove any catalog. The example below asks if the user wants to delete the currently selected catalog. If the user confirms it stops the Indexing services, deletes the catalog and then starts the Indexing service again. Afterwards it again calls FillCatalogList() to refresh the list of catalogs in the list view.

C#
private void RemoveCatalog_Click(object sender, EventArgs e)
{
    string CatalogName = ListOfCatalogs.SelectedItems[0].Text;
    
    // ask the user to confirm the deletion of the catalog
    if (MessageBox.Show(this, ConfirmDeleteCatalog, CatalogName,
                     MessageBoxButtons.YesNo, 
                     MessageBoxIcon.Question) == DialogResult.Yes)
    {
        AdminIndexServerClass Admin = new AdminIndexServerClass();
        
        Admin.Stop();
        Admin.RemoveCatalog(CatalogName, true);
        Admin.Start();
        
        // refresh the list of catalogs
        FillCatalogList(ListOfCatalogs);
    }
}

How to retrieve the list of search scopes of a catalog?

Each catalog has search scopes, the folders which are included in the catalog. A search scope can be inclusive (by default) or exclusive, meaning this folder will not be included in the catalog. With exclusive you can define sub-folders which should be excluded by this catalog. Listing all the search scopes of the catalog works very similar to the listing of all catalogs of the Indexing Server. First obtain a reference to the catalog by calling the method GetCatalogByName() on an instance of type AdminIndexServerClass. This returns an object of type object and you need to query for the ICatAdm interface using the “as” keyword.

C#
private ICatAdm GetCatalog(string CatalogName)
{
    AdminIndexServerClass Admin = new AdminIndexServerClass();
    
    // find the catalog by name
    return Admin.GetCatalogByName(CatalogName) as ICatAdm;
}

Next you call FindFirstScope() on ICatAdm interface to get the first search scope which returns true if one is found otherwise false. You call FindNextScope() on ICatAdm interface to find subsequent search scopes which again returns true when one is found otherwise false. You do this again in a loop till it returns false. Each time you call GetScope()to obtain a reference to the current search scope. This again returns an object of the type object and you query for the IScopeAdm interface via the “as” keyword. That interface then provides a list of properties about the search scope itself:

C#
private void FillScopeList(string CatalogName)
{
    // remove any existing item in the scope list
    ListOfScopes.Items.Clear();
    
    // get a handle to the newly selected catalog
    ICatAdm Catalog = GetCatalog(CatalogName);
    
    // search for the first scope item
    bool FoundScope = Catalog.FindFirstScope();
    
    // loop through all the scope items
    while (FoundScope)
    {
        // get a handle to the current scope item
        IScopeAdm Scope = Catalog.GetScope() as IScopeAdm;
        
        // create a new list view item and set its values
        ListViewItem Item = ListOfScopes.Items.Add(Scope.Alias);
        Item.SubItems.Add(Scope.ExcludeScope.ToString());
        Item.SubItems.Add(Scope.Logon);
        Item.SubItems.Add(Scope.Path);
        Item.SubItems.Add(Scope.VirtualScope.ToString());
        
        // search for the next scope item
        FoundScope = Catalog.FindNextScope();
    }
    
    // select the first scope in the list
    if (ListOfScopes.Items.Count > 0)
        ListOfScopes.SelectedIndices.Add(0);
}

The example above adds all search scopes of a catalog to a list view. This includes the path of the search scope and whether it is exclusive. The VirtualScope is only set if this catalog indexes a web site.

How to start, stop, pause or continue a catalog?

You can start, stop, pause or continue an individual catalog. First you need to get a reference to the catalog by calling GetCatalogByName on an instance of the type AdminIndexServerClass. Then you query again for the ICatAdm interface. The ICatAdm interface also provides methods to find out if the catalog is running or paused:

  • StartCatalog()- starts the Indexing catalog.
  • StopCatalog()- stops the Indexing catalog.
  • PauseCatalog()- pauses the Indexing catalog.
  • ContinueCatlog()- continues a paused Indexing catalog.
  • IsCatalogRunning()- returns true if the Indexing catalog is running.
  • IsCatalogPaused()- returns true if the Indexing catalog is paused.

How to add or remove a search scope to a catalog?

First you need to obtain a reference to the catalog and then call the method AddScope(). You pass along the folder to index and true if the search scope is exclusive or false if it is inclusive. The example below shows a dialog so the user can enter the folder of the search scope and select if it is exclusive or inclusive. Next it gets the name of the currently selected catalog, obtains the catalog object for it and then adds the search scope by calling AddScope() on the Catalog object. It then asks the user if a full scan for it should be performed. In that case it gets a reference to the newly created search scope by calling GetScopeByPath() on the Catalog object and then calls Rescan() on it passing along true for a full scan. Finally it calls the method FillScopeList() to refresh the list of search scopes in the list view.

C#
private void AddScope_Click(object sender, EventArgs e)
{
    string CatalogName = ListOfCatalogs.SelectedItems[0].Text;
    
    // the dialog to create a new scope
    AddNewScope AddNew = new AddNewScope();
    
    // we want to create the scope
    if (AddNew.ShowDialog(this) == DialogResult.OK)
    {
        // get the catalog handle
        ICatAdm Catalog = GetCatalog(CatalogName);
        
        // create the new scope
        Catalog.AddScope(AddNew.Path, AddNew.ExcludeFolder, 
                                                 null, null);
        
        // ask the user if we want to scan the new search scope
        if (MessageBox.Show(this, PerformFullScan, this.Text,
                    MessageBoxButtons.YesNo, 
                    MessageBoxIcon.Question) == DialogResult.Yes)
        {
            // get a reference to the search scope we just added
            IScopeAdm Scope = 
                Catalog.GetScopeByPath(AddNew.Path) as IScopeAdm;
            
            // to a full scan
            Scope.Rescan(true);
        }
        
        // refresh the list of scopes
        FillScopeList(ListOfCatalogs.SelectedItems[0].Text);
    }
}

Adding or removing search scopes does not require stopping or restarting the catalog service. To remove a search scope you call the method RemoveScope() on the Catalog object and pass along the path of the search scope. The example below asks if the user wants to delete the currently selected search scope. If the user confirms it deletes the search scope and afterwards it again calls FillScopeList() to refresh the list of search scopes in the list view.

C#
private void RemoveScope_Click(object sender, EventArgs e)
{
    string CatalogName = ListOfCatalogs.SelectedItems[0].Text;
    string ScopePath = 
         ListOfScopes.SelectedItems[0].SubItems[3].Text
    
    // ask the user to confirm the deletion of the search scope
    if (MessageBox.Show(this, ConfirmDeleteScope, ScopePath,
                 MessageBoxButtons.YesNo, 
                 MessageBoxIcon.Question) == DialogResult.Yes)
    {
        // get the catalog handle
        ICatAdm Catalog = GetCatalog(CatalogName);
        
        // delete the selected scope
        Catalog.RemoveScope(ScopePath);
        
        // refresh the list of scopes
        FillScopeList(ListOfCatalogs.SelectedItems[0].Text);
    }
}

Summary

The administrative API of Indexing Server is very simple. The AdminIndexServerClass type gives you full control over the Indexing Server itself. The ICatAdm interface and CatAdm type provide full control over each catalog. The IScopeAdm interface and ScopeAdm type provide full control over each search scope. This makes it very easy for you to add new catalogs and search scopes or remove existing catalogs and search scopes programmatically. You also have the ability to force a full or partial scan of search scopes so that additions or changes are available to your application instantly. Refer to the MSDN help for more details about the Indexing Server API. The enclosed sample application provides a sample administrative interface to Indexing Server using the very same API. If you have comments on this article or this topic, please contact me @ klaus_salchner@hotmail.com. I want to hear if you have learned something new. Contact me if you have questions about this topic or article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Chief Technology Officer
Canada Canada
Experienced technology leader who is passionate about building cloud and enterprise based products. Building an innovative and modern cloud product is a people business which requires to assemble a team of passionate and continuously improving technologists, establishing a vision and framework to buy into, and then let your team execute and drive that product vision. Ship frequently, build a strong feedback loop with your customers and partners and continuously iterate till you get it right.

I am a seasoned executive which has more then twenty-five years of experience running product development organizations around the globe. Has managed multimillion dollar budgets, experience with outsourcing and off-shoring in India and Vietnam for more than ten years, and experience in the Microsoft and Java/J2EE platform. Managed many initiatives across organizational boundaries and has often been called upon by the CEO, COO or SVP to manage teams, projects or systems from crisis to success. Proven track record to deliver world class enterprise software deployed behind the firewall and in the Cloud by large customers like IBM, HP, US Navy, US Army, Department of Defence, Lockheed Martin, Boeing and many more. Delivered software translated into more than thirty languages, deployed by more than 50% of the Fortune 100 companies and used by more than twenty million users in more than 1300 companies. Has run multiple Cloud operations with uptime SLA’s of four nines. Delivered numerous innovations which resulted in millions of dollar revenue and has been featured in several case studies by Microsoft. Active contributor in the online technical community.

You can read more about the four Product leadership experiences which I have demonstrated over my career and which I deeply care about at my LinkedIn profile

Comments and Discussions

 
Generalabout custom properties Pin
OldDeda8-May-07 0:13
OldDeda8-May-07 0:13 
QuestionCan I force indexing server to do index on demand? Pin
.NetRams19-Apr-07 20:34
.NetRams19-Apr-07 20:34 
QuestionPermission Problems Pin
Fabian Gonzalez Quiros13-Sep-06 10:42
Fabian Gonzalez Quiros13-Sep-06 10:42 
AnswerRe: Permission Problems Pin
Sanin16-Jan-07 8:43
Sanin16-Jan-07 8:43 
GeneralRe: Permission Problems Pin
Muhammad Nauman Yousuf7-Apr-08 19:34
Muhammad Nauman Yousuf7-Apr-08 19:34 
QuestionI am getting error while using AddNewCatalog Pin
naveen.srikakolanu26-Jun-06 19:12
naveen.srikakolanu26-Jun-06 19:12 
QuestionPermissions problems Pin
silverbeetle14-Jun-06 3:54
silverbeetle14-Jun-06 3:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.