17
votes

Currently I'm trying to query the Windows Search Service from a SQL Server 2008 R2 instance (also tested on SQL Server 2012) . Windows Search is being exposed as an OLE DB datasource, giving me several options to query the search index. When configuring a new Linked Server in SQL Server, Management Studio gives me the option to select the Microsoft OLE DB Provider for Search, implying that I should be able to connect to it from SQL Server. It turns out to be a challenge to get this up and running however. Below you'll find the error message I stumbled upon.

OLE DB provider "Search.CollatorDSO" for linked server "TESTSERVER" returned message "Command was not prepared.".
Msg 7399, Level 16, State 1, Line 2
The OLE DB provider "Search.CollatorDSO" for linked server "TESTSERVER" reported an error. Command was not prepared.
Msg 7350, Level 16, State 2, Line 2
Cannot get the column information from OLE DB provider "Search.CollatorDSO" for linked server "TESTSERVER".

Things get even more interesting. Although the Linked Server solution isn't working, I'm able to wrap code that queries Windows Search in a CLR Function (using MSDN: Querying the Index Programmatically) and use if successfully within SQL Server. This is however less desirable, because of the steps needed to set it up (deploying the library, configuring permissions, etc.). I've tried several parameter settings, without any luck. I've also tried enabling some of the Search.CollatorDSO provider options, like allowing the provider to be instantiated as an in-process server. I'm currently using the settings below. For security I'm using the login's current security context.

  • Provider: Microsoft OLE DB Provider for Search
  • Data source: (local)
  • Provider string: Provider=Search.CollatorDSO.1;EXTENDED?PROPERTIES="Application=Windows"
  • Location: -

Additionally I need to search network drives, can this be done using shared Windows libraries?

I'm aware more people have been struggling with this problem over the last few years. I'm wondering if someone has been able to get this up and running, or could point me in the right direction.

OLEDB Works

Normal ADO/OLEDB components can query the Windows Search service with the connection string:

provider=Search.CollatorDSO.1;EXTENDED PROPERTIES="Application=Windows"

And an example query:

SELECT TOP 100000 "System.ItemName",
    "System.ItemNameDisplay",
    "System.ItemType",
    "System.ItemTypeText",
    "System.Search.EntryID",
    "System.Search.GatherTime",
    "System.Search.HitCount",
    "System.Search.Store",
    "System.ItemUrl",
    "System.Filename",
    "System.FileExtension",
    "System.ItemFolderPathDisplay",
    "System.ItemPathDisplay",
    "System.DateModified",
    "System.ContentType",
    "System.ApplicationName",
    "System.KindText",
    "System.ParsingName",
    "System.SFGAOFlags",
    "System.Size",
    "System.ThumbnailCacheId"
FROM "SystemIndex"
WHERE CONTAINS(*,'"Contoso*"',1033)

You can try the query directly on SQL Server in SQL Server Management Studio by attempting to run:

SELECT *
FROM OPENROWSET(
        'Search.CollatorDSO', 
        'Application=Windows', 
        'SELECT TOP 100 "System.ItemName", "System.FileName" FROM SystemIndex');

Which gives the errors:

OLE DB provider "Search.CollatorDSO" for linked server "(null)" returned message "Command was not prepared.".  

Msg 7399, Level 16, State 1, Line 1  
The OLE DB provider "Search.CollatorDSO" for linked server "(null)" reported an error. Command was not prepared.  
Msg 7350, Level 16, State 2, Line 1  
Cannot get the column information from OLE DB provider "Search.CollatorDSO" for linked server "(null)".  

Bonus Reading

1
Did you have any progress in finding a solution? any source code sample about it?Kiquenet

1 Answers

-1
votes
Have a look at this code..It may help

USE [YourDB]
    GO

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO

    Create PROC [dbo].[SearchAllTables]
    @SearchStr nvarchar(100)
    AS
    BEGIN
    DECLARE @dml nvarchar(max) = N''        
    IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE dbo.#Results
    CREATE TABLE dbo.#Results
     ([tablename] nvarchar(100), 
      [ColumnName] nvarchar(100), 
      [Value] nvarchar(max))  
    SELECT @dml += ' SELECT ''' + s.name + '.' + t.name + ''' AS [tablename], ''' + 
                    c.name + ''' AS [ColumnName], CAST(' + QUOTENAME(c.name) + 
                   ' AS nvarchar(max)) AS [Value] FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) +
                   ' (NOLOCK) WHERE CAST(' + QUOTENAME(c.name) + ' AS nvarchar(max)) LIKE ' + '''%' + @SearchStr + '%'''
    FROM sys.schemas s JOIN sys.tables t ON s.schema_id = t.schema_id
                       JOIN sys.columns c ON t.object_id = c.object_id
                       JOIN sys.types ty ON c.system_type_id = ty.system_type_id AND c .user_type_id = ty .user_type_id
    WHERE t.is_ms_shipped = 0 AND ty.name NOT IN ('timestamp', 'image', 'sql_variant')

    INSERT dbo.#Results
    EXEC sp_executesql @dml

    SELECT *
    FROM dbo.#Results
    END