Use SharePoint Web Services and PowerShell to Work with Search

Use SharePoint Web Services and PowerShell to Work with Search

  • Comments 2
  • Likes

Summary: Learn how to use the web services in SharePoint with Windows PowerShell to query for search results.

Microsoft Scripting Guy, Ed Wilson, is here. Today our Guest Blogger Week continues with an excellent post about using Windows PowerShell cmdlets with SharePoint. The post is written by a return guest, Josh Gavant. For those of you who might not recall from his previous posts, here is a little bit about Josh:

Josh is a premier field engineer (PFE) with Microsoft Services, and he specializes in SharePoint and Windows PowerShell. When he is not playing with computers, he enjoys music and running with his wonderful wife in beautiful Chicago.

Contact information:
Blog: Beside the Point
Twitter: @joshugav

Note: The script for today’s blog is posted in the Scripting Guys Script Repository.

Take it away Josh!

Many SharePoint services can be accessed directly by using web services calls. An advantage of utilizing web services instead of the SharePoint object model is that service calls work neatly and predictably from clients, with no need for any additional DLLs or installations. Customers who are building custom applications on top of SharePoint often take advantage of the web services in SharePoint to layer custom interfaces and services on top of SharePoint. We can also take advantage of these services via Windows PowerShell as an aid in testing and as a component of proper scripts.

To access the web services in SharePoint, we will utilize the New-WebServiceProxy cmdlet in Windows PowerShell, which automatically retrieves the Web Service Description Language (WSDL) document for a web service and dynamically builds a proxy that is able to connect to that service. Like other object frameworks (such as COM, .NET, and WMI), Windows PowerShell does us the favor of abstracting the differences between different types of objects. It then surfaces a web service in the same manner as other Windows PowerShell objects, with members like any other Windows PowerShell member.

Of the several SharePoint front-end web services that are available, we will focus on retrieving search results through QueryService. First, we’ll complete the simple task of building a proxy object. Then we’ll build up the necessary elements to send off a query through our proxy. Finally, we’ll wrap things up in a function to make life easier.

The only trick to remember when calling a SharePoint web service is that you need to authenticate yourself. So use the following paradigm to create a web service proxy for the Search service (substitute your value for $WebApplicationPath):

$WebApplicationPath = “<Path_To_WebApplication>”

$SearchPath = “/_vti_bin/Search.asmx”

$SearchWS = New-WebServiceProxy -Uri ($WebApplicationPath + $SearchPath) -UseDefaultCredential

Part of the purpose of creating the proxy in Windows PowerShell is to explore the interfaces that it offers. In the spirit of exploration, run the following commands:

$SearchWS | Get-Member

$SearchWS.Query

Note that the second command returns a MethodInfo object with information about the method to be called. Two methods of interest are returned by Get-Member from the Search service proxy: Query and QueryEx. Both take an XML document describing the query, but they differ in the results they return. Query returns results in XML form, and QueryEx returns results as an ADO.NET dataset. Both can be treated as first class objects in Windows PowerShell, but I like using ADO.NET better in Windows PowerShell, so we will use QueryEx.

Now we must build our QueryXML. When we have completed building our Query XML, we will call the QueryEx method. You can find the Microsoft.Search.Query schema on MSDN. We will use this form, relying on defaults for some excluded nodes as shown here:

$KeywordQuery = “Test SharePoint”

$Count = 10

$QueryXml = @"

<QueryPacket xmlns="urn:Microsoft.Search.Query" >

    <Query>

        <Context>

            <QueryText type="STRING">$KeywordQuery</QueryText>

        </Context>

        <Range>

            <Count>$Count</Count>

        </Range>

        <IncludeSpecialTermResults>false</IncludeSpecialTermResults>

        <PreQuerySuggestions>false</PreQuerySuggestions>

        <HighlightQuerySuggestions>false</HighlightQuerySuggestions>

        <IncludeRelevantResults>true</IncludeRelevantResults>

        <IncludeHighConfidenceResults>false</IncludeHighConfidenceResults>

    </Query>

</QueryPacket>

"@

Note the use of an expandable here-string. This gives me the best of both worlds—between the opening and closing lines, I need not worry about quotation marks, and yet I can use variables to specify values in the text. Originally, I wrote this script by using [xml] objects, but then I decided that using a string of XML would be easier.

In this case, I declared values for $KeywordQuery and $Count right before setting $QueryXml. When I wrap this into a function, $KeywordQuery and $Count will be the function’s parameters.

With my setup work out of the way, I’m ready to call the proxy’s method with my XML. The return from this method is an ADO.NET dataset, which is a collection of data tables. I have written the Query XML in such a way that there is only one table (RelevantResults) in this dataset; if it is written in other ways, there could be two or three tables. To be on the safe side, I retrieve the RelevantResults table from the set. Windows PowerShell will automatically enumerate through each data row in the data table and create an object that is based on the values of columns in the row. Here are the relevant commands:

$Results = $SearchWS.QueryEx( $QueryXml )

$Results.Tables[“RelevantResults”]

The default output contains a number of properties, some of which may not be relevant to you. A nice set of properties to start with is returned by the following command:

$Results.Tables[“RelevantResults”] | Format-Table Title, Author, ContentClass, Path

If you wanted to retrieve different properties from the search engine, you could modify the XML to specify any managed property in SharePoint Search (use Get-SPEnterpriseSearchMetadataManagedProperty to get a list). I will leave that as an exercise for you.

We have now presented all the steps to query SharePoint search via Windows PowerShell. Let us wrap it into a nice, easy-to-use function. The complete function is shown here. (I have also uploaded it to the Scripting Guys Script Repository for ease of copying.)

function Query-SPSearch {

    param(

        [Parameter(Mandatory=$true)]

        [String]

        $WebApplicationPath,

        [Parameter(Mandatory=$true)]

        [String]

        $KeywordQuery,

        [Parameter()]

        [Int32]

        $Count = 10

    )

$QueryXml = @"

<QueryPacket xmlns="urn:Microsoft.Search.Query" >

    <Query>

        <Context>

            <QueryText type="STRING">$KeywordQuery</QueryText>

        </Context>

        <Range>

            <Count>$Count</Count>

        </Range>

        <IncludeSpecialTermResults>false</IncludeSpecialTermResults>

        <PreQuerySuggestions>false</PreQuerySuggestions>

        <HighlightQuerySuggestions>false</HighlightQuerySuggestions>

        <IncludeRelevantResults>true</IncludeRelevantResults>

        <IncludeHighConfidenceResults>false</IncludeHighConfidenceResults>

    </Query>

</QueryPacket>

"@

    $ServicePath = "/_vti_bin/search.asmx"

 

    $SearchWS = New-WebServiceProxy -Uri ($WebApplicationPath + $ServicePath) -UseDefaultCredential

    $Results = $SearchWS.QueryEx( $QueryXml )

    # we excluded all other result sets, but just in case get the one we want:

    $Results.Tables["RelevantResults"]

}

Typical usage for this function would be as follows:

Query-SPSearch -WebApplicationPath “http://sharepoint10” -KeywordQuery “SharePoint test” -Count 20 | Format-Table Title, Author, Path

I hope this helps you get started down the road to discovering and utilizing the web services in SharePoint. Be sure to check out my SharePoint and Windows PowerShell posts on my Beside the Point blog on MSDN. Thanks!

~Josh

Thanks, Josh, for sharing your time and knowledge. I had heard about the web services in SharePoint, but I have never played around with them, and I have since completely forgotten about them. This gives me something with which to experiment. Sweet! Join me tomorrow for a great guest post by Jan Egil Ring about working with Microsoft Exchange Web Services—seems to be more than one theme at work here. See you!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • <p>Hi Josh,</p> <p>very interesting indeed!</p> <p>Thanks for showing us how to query the SharePoint webservice!</p> <p>I&#39;d like to try it out ... but unfortunately we don&#39;t host Sharepoint here!</p> <p>What is a pity too, if you ask me ...</p> <p>Klaus</p>

  • <p>how I can scope down the queryXML if I have to use contextual scope with powershell, I am in a situation where writing a script to monitor site brings up the results all the time, however I know how to put scope in queryxml but not sure how I can use contextual scope with saying &quot;This Site&quot;</p> <p>And yes your script helped me alot and save my daily on call checklist (stupid) task ....just wanted to thank you for that.</p>