Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (0)


Add MS Index Server Search capabilities to your Delphi appGo to Kirill Plugin's websiteFormat this article printer-friendly!Bookmark function is only available for registered users!
Administering MS Index Server and executing full-text search queries
Product:
Delphi 5.x (or higher)
Category:
System
Skill Level:
Scoring:
Last Update:
01/26/2006
Search Keys:
delphi delphi3000 article borland vcl code-snippet index server interface Windows-NT Windows-2000
Times Scored:
8
Visits:
3316
Uploader: Kirill Plugin
Company: IBM
Reference: N/A
 
Question/Problem/Abstract:
Microsoft Index Server is a standard component of Windows NT/2000 products. Windows NT 4 Server comes with Index Server 2, and 2000 Server and Professional come with Index Server 3. According to Microsoft documentation "Indexing Service is a base service of Microsoft® Windows NT®/Windows® 2000 that extracts content from files and constructs an indexed catalog to facilitate efficient and rapid searching". Primarily it is used as a Web search engine.
In this article I will focus on how to access the MS Index Server from Delphi app in order to perform administrative tasks and execute search queries. For detailed information on MS Index
Server including query language refer to MSDN SDK Documentation for Indexing Service.
Answer:



First things first

Before you go ahead with researching Index Server and playing with source code from this article you need to import two type libraries.
First, ixsso.dll, will provide you with Query and Utility objects. Second, ciodm.dll, will provide AdminIndexServer, CatAdm, and ScopeAdm objects. (Make sure the 'Generate Component Wrapper' box is checked in Import Type Library dialogue.)
The following is a quote from MS documentation:
Indexing Service Query Automation Objects
(Object name - Description)
Query - Manages the query definition and result-set creation and navigation.
Utility - Helpful utilities for managing the queries and result sets.
Indexing Service Administration Automation Objects
AdminIndexServer - Manages Indexing Service. Allows access to all the functionality provided by the Microsoft Management Console (MMC) snap-in.
CatAdm - Manages the collection of scopes for a catalog.
ScopeAdm - Manages an individual scope.

Get in touch with Index Server
Now with your project Index Server automation objects (and interfaces) aware here is the sample form's OnCreate event (see source code).

procedure TForm1.FormCreate(Sender: TObject);
var
   IndexServerAdmin: TAdminIndexServer; //Index server administration automation object
   CatAdm : TCatAdm; //Catalog administration automation object
begin
   //Both IndexQuery and IndexUtil objects are declared in main unit
   IndexQuery := TCissoQuery.Create(nil);
   IndexUtil := TCissoUtil.Create(nil);
   //Let's display a list of catalogs available on local index server
   IndexServerAdmin := TAdminIndexServer.Create(nil);
   //Check if the server is running.
   CheckBox1.Checked := IndexServerAdmin.IsRunning;
   if IndexServerAdmin.FindFirstCatalog then
      begin
         CatAdm := TCatAdm.Create(nil);
         CatAdm.ConnectTo(InsexServerAdmin.GetCatalog() as ICatAdm);
         //Add catalog name to the ListBox.
         ListBox1.Items.Add(CatAdm.CatalogName);
         CatAdm.Free;
         while InsexServerAdmin.FindNextCatalog do
            begin
               CatAdm := TCatAdm.Create(nil);
               CatAdm.ConnectTo(InsexServerAdmin.GetCatalog() as ICatAdm);
               //Add catalog name to the ListBox.
               ListBox1.Items.Add(CatAdm.CatalogName);
               CatAdm.Free;
            end;
      end;
   InsexServerAdmin.Free;
end;

IndexServerAdmin.IsRunning here is used just to set the CheckBox state.
InsexServerAdmin.GetCatalog() returns ICatAdm type, and CatAdm.ConnectTo is used to connect CatAdm automation object to index server. Index server automation object allows you to check the server status (IsRunning, IsPaused methods) as well as change status (Start, Stop, Pause methods), catalogs enumeration (FindFIrstCatalog, FindNextCatalog methods - see sample code), and retrieve catalog (GetCatalog, GetCatalogByName).

Admin Index Server resources
Here is the code on the ListBox1 (list of catalogs) OnClick method.
As soon as catalog is selected it's location (location of the catalog file) is displayed in the Label7.
Also scopes are listed in a ListBox2. Scope in fact is a resource (folder) all contents of which are indexed.

procedure TForm1.ListBox1Click(Sender: TObject);

var
   IndexServerAdmin: TAdminIndexServer;
   CatAdm : TCatAdm;
   ScopeAdm: TScopeAdm;
begin
   {This is a Search button. Will be used later.
   It is disabled until catalog is selected from a ListBox1.}

   Button1.Enabled := true;
   IndexServerAdmin := TAdminIndexServer.Create(nil);
   CatAdm := TCatAdm.Create(nil);
   CatAdm.ConnectTo(IndexServerAdmin.GetCatalogByName( ListBox1.Items[ListBox1.ItemIndex] ) as ICatAdm);
   Label7.Caption := 'Catalog location: ' + CatAdm.CatalogLocation ;
   //Enumerate scopes
   ListBox2.Clear ;
   if CatAdm.FindFirstScope then
      begin
         ScopeAdm := TScopeAdm.Create(nil);
         ScopeAdm.ConnectTo(CatAdm.GetScope() as IScopeAdm);
         ListBox2.Items.add(ScopeAdm.Path);
         ScopeAdm.free;
         while CatAdm.FindNextScope do
            begin
               ScopeAdm := TScopeAdm.Create(nil);
               ScopeAdm.ConnectTo(CatAdm.GetScope() as IScopeAdm);
               ListBox2.Items.add(ScopeAdm.Path);
               ScopeAdm.free;
            end;
      end;
   CatAdm.Free;
   IndexServerAdmin.Free;
end;

For each of catalogs and scopes you can check and set the status. Also you can add new catalog to server, as well as add new scope to catalog, which in turn is a collection of scopes.
A couple important notes here. Administrative tasks (like adding a catalog) should be applied to the index server when it is stopped. As soon as new catalog or scope added and server is index server started again, give some time for the first run of contents indexing. All further content updates would be followed with incremental index updates (at list it works this way on NTFS).

Executing the search query
Here is the search button Button1 OnClick event code. The important point here is that it does not use ADO provider for Index Server thus excluding a lot of overhead work. Query results though are obtained as TADODataSet object which you can use for further search results processing.
In this sample code I used DBGrid1:TDBGrid and DataSource1:TDataSource to display search results.

procedure TForm1.Button1Click(Sender: TObject);
var
   i, ii: Integer;
   ds: TADODataSet;
   rs: _Recordset; //Defined in ADOdb unit
begin
   IndexQuery.Reset ;
   //Enter query text or just a word in Edit1
   IndexQuery.Query := '$contents "' + Edit1.Text + '"';
   //List fields you want the query to return
   IndexQuery.Columns := 'DocTitle,Path,Write,Rank';
   //Define query result sort order
   IndexQuery.SortBy := 'Rank [d]';
   IndexQuery.MaxRecords := 1000;
   //Catalog selcted in Listbox1
   IndexQuery.Catalog := ListBox1.Items[ListBox1.ItemIndex];
   Memo1.Lines.Clear;
   //Output simple status report
   Memo1.Lines.Add( 'Searching for ' + IndexQuery.Query + ' in "' + IndexQuery.Catalog + '"');
   try
      ds := TADODataSet.Create(nil);
      //Retrieving query results - the trickiest part.
      ds.RecordSet := (IndexQuery.CreateRecordset('nonsequential') as _Recordset);
      ii := ds.Recordset.RecordCount - 1;
      memo1.Lines.Add('num of docs: ' + IntToStr(ii));
   except
      memo1.Lines.Add('did not work on "' + IndexQuery.Catalog + '"');
   end;
   //Assign Recordset object to ADODataSet's RecordSet property.
   ADODataSet1.RecordSet := ds.Recordset;
   ds.Close;
   ds.Free;
end;


Enjoy!





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment













 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
E. Irigoyen
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)