Search code examples
iis-7asp-classicwindows-server-2008-r2indexing-service

How to query the Windows 2008 x64 Index Service from 32-bit ASP applications?


Recently I stumbled upon a problem that involves moving asp classic sites from a w2k3 server to a w2k8 64 environment. It involved getting indexing services to work with asp classic. I searched every where tried many solutions and they all failed.

The problem: running a 64bit indexing service on a 32bit application pool (for asp classic) ASP pages running request to the indexing service resulted in error where the server object failed to load. although the indexing service was running and the folder containing documents of the site where indexed the indexing service was running in 64bit mode and the pool in 32bit mode. It was not possible to run.

Some of the suggested solutions was to rewrite the code to use the new 'windows search' But since this is also running in 64bit it could not be run in 32bit application mode. Switching to 32bit compatible mode off in the pool resulted of not working databases and other com objects used by the asp sites.


Solution


  • After a couple of days I almost given up but in the middle of the night I got a brilliant idea to get it all working. What if I make a ajax call to a sub domain on the webserver which is running in 64bit mode with virtual directories containing the indexed directories of the sites running in 32bit application mode.

    Next day after a restless sleep I got to work, added a new subdomain in IIS7 added virtual directories to the indexed directories of the websites. and added a 'indexer.asp' page which contains a request handler.

    <%@ Language=VBScript %><%
    
    
    Option explicit
    response.buffer=true
    
    dim RequestIndex, strFileError, RequestSearchString, FSOA, RequestMax
    
    
    RequestIndex=request.querystring("Index")
    RequestSearchString=request.querystring("Search")
    RequestMax=request.querystring("Size")
    
    
    ' INDEXER 
    sub DoIndexSearch(target, RequestIndex)
    dim foundfilearray:foundfilearray=false
    dim ixQuery   ' Index Server query object.
    set ixQuery = Server.CreateObject("ixsso.Query")
    if (Err.description <> "") Then
        strFileError= ("<div><strong>Query object Error : " & Err.description & ".</strong></div>")
        response.write strFileError 
        Exit sub
    end if
    
    ixQuery.Query =(target)
    'ixQuery.SortBy  = "DocLastSavedTm[d]"
    ixQuery.SortBy  = "Rank[d]"
    ixQuery.Columns  = "FileName," 'Parameter: columns returned (one this case a one dimensional array)
    ixQuery.LocaleID = 1043  'Parameter: language 
    ixQuery.MaxRecords =RequestMax   'Parameter:  max returned documents 
    ixQuery.Catalog = RequestIndex 'IndexService ' Which indexing service
    
    ' Create a search utility object to allow us to specify the search type as deep,meaning  it will search recursively down through the directories
    dim util      
    set util = Server.CreateObject("ixsso.Util")
    util.AddScopeToQuery ixQuery, Server.MapPath(RequestIndex), "deep"
    if (Err.description <> "") Then
        strFileError= ("<div><strong>Search Utility Error : " & Err.description & "</strong></div>")
        response.write strFileError 
        Exit sub
    end if
    
    
    ' Run the query (i.e. create the recordset).
    dim QueryRS
    set queryRS = ixQuery.CreateRecordSet("nonsequential")
    ' Check the query result. If it timed out or return no records, then show
    ' an appropriate message. Otherwise, show the hits.
    if (Err.description <> "") Then
        strFileError= "<div><strong>search error : " & Err.description & "</strong></div>"
        response.write strFileError 
        queryRS.close
        set queryRS = nothing
        set ixQuery = nothing
        set util = nothing 
        Exit sub
    
    elseif queryrs.recordcount = 0 then
        strFileError="<div><strong>no documents found.</strong></div>"
        response.write strFileError 
        queryRS.close
        set queryRS = nothing
        set ixQuery = nothing
        set util = nothing 
        Exit sub
    else
        FSOA= QueryRS.getrows()
        queryRS.close
        set queryRS = nothing
        set ixQuery = nothing
        set util = nothing 
        Exit sub
    end if
    
    end Sub
    
    
    call DoIndexSearch(RequestSearchString,RequestIndex)
    
    
    ' TESTING PURPOSE  
    dim strTestResult
    strTestResult= "<html><head></head><body style=""font-family:Verdana, arial"">" 
    strTestResult=strTestResult& "<h1>Testing 64bit classic asp indexing using windows 2008 64bit server</h1>" 
    strTestResult=strTestResult& "<h3>Search in index <em>"&RequestIndex&"</em>  for <em>"&RequestSearchString&"</em> with max <em>"&requestMax&"</em> results</h3>" 
    strTestResult=strTestResult& "<p>Using a seperate website running a 64bit classic pool, wich contains a virtual directory named after the Index which contains the path to the directory of the website that is indexed.</p>" 
    strTestResult=strTestResult& "<p>The returned results is a one dimensional array containing the filenames where searchstring is found in. This array can be passes back using ajax/json</p>"  
    
    if isarray(fsoa) then
        strTestResult=strTestResult& " <hr>" 
        strTestResult=strTestResult& "<fieldset><legend>Found items for "&RequestSearchString&"  </legend>"
    
        dim xloop:xloop=0
        strTestResult=strTestResult& " <ol>" 
    
        for each xloop in fsoa
            strTestResult=strTestResult& "<li>"&Xloop&" </li>" 
        next
    
        strTestResult=strTestResult& " </ol></fieldset></body></html>"
        strTestResult=strTestResult& "<hr>" 
        strTestResult=strTestResult& "<h1>AJAX return array</h1>" 
    else
        strTestResult=strTestResult& " no items found" 
    end if
    
    ' response.write strTestResult ' (Remark when done testing)
    ' END TESTING
    
    
    
    ' RETURN INDEXING RESULT TO AJAX/JSON CALLER (one dim array)
    if  strFIleError="" then
        xloop=0
        dim ajaxresult
    
        for each xloop in FSOA
            ajaxresult=ajaxresult & ucase(Xloop) &"|" 
        next
    
        ajaxresult=Left(ajaxresult,Len(ajaxresult)-1)
        response.write ajaxresult
    end if
    
    
    %>
    

    Then I made a request page on one of the websites running in 32bit application mode:

    dim FSOA 'return documents file array
    
    'search inside documents 
    sub DoSearchText(target, indexservice)
    'target = search string
    'indexservice = catalog name (index service)
    
    dim IndexArray() 'one dimensional array for index result
    dim xmlhttp, tempArray, IndexUrl
    
    'url to the 64bit indexer subdomain
    IndexURL = ("http://indextest.subdomain.local/indexer.asp?Index="&IndexService&"&Search="&target&"&Size=50") 
    set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP") 
    xmlhttp.open "GET", IndexURL, false 
    xmlhttp.send ""  
    
    if xmlhttp.status >= 400 and xmlhttp.status <=599 then
        response.write " error processing: " &xmlhttp.status &" - "&xmlhttp.statusText
    else
        tempArray= xmlhttp.responseText 
    end if
    
    set xmlhttp = nothing  
    'put result into a array
    FSOA= split(tempArray,"|")
    end Sub
    
    
    call DoSearchText("chapter one", "sitebooks")
    
    if isarray(FSOA) then
    
        dim docloop
        for each docloop in FSOA
            response.write "<div>"&docloop&"</div>"
        next
    else
        response.write "No documents found"
    end if
    

    `

    Explanation:

    • Parse indexing service catalog name, search string, max resulted documents
    • In subdomain create virtual directories (named as the index catalog) that redirects to the original location of the directory that has been indexed
    • Add a indexer.asp page that handles the request calls
    • alter existing request object code of original webpage to make a ajax call to above subdomain

    Benefits:

    • Make a Ajax request from asp classic website running in 32bit application mode to a 64bit application and return results.
    • You can also include adobe PDF Ifilter (64bit) to index PDF and read inside PDF files.
    • Easy to alter existing asp code of sites. Minor changes
    • Run indexer on separate 64bit pool and subdomain
    • Add multiple catalogs easy maintained on one location
    • Making the impossible possible: running asp classic with 64bit indexing service in 32bit application mode