Configuring SharePoint 2013 Search with PowerShell

Post courtesy Partner Solution Consultant Priyo Lahiri:

I wrote this script for a demo during our Practice Accelerater for SharePoint 2013. If you have attended the session you have already seen this in action. If not, here is the script for you to try out in your lab.

Disclaimer: before we proceed you should know that this script has been tested in my lab to work in a very specific scenario. If you wish to use this, your environment should exactly look like mine. In other words, we are not responsible if this script ruins your farm Smile.

Take a note on the environment first:

SharePoint Farm:

  • 2 web front end servers
  • 2 application servers
  • 1 SQL Server

Following are the services running on the server:

clip_image002

This script will provision Search on all the servers and configure our WFEs to host Query Processing Role.

Very important: if your environment doesn’t look like this, STOP here.

If you already have Search Configured, which would be your default setting if you have run the Farm Configuration Wizard, don’t use this script.

Follow these TechNet guidance to understand more:

As you can see from the above screenshot, my environment doesn’t even have Search Service started, so we are good to go in using this script. It’s ok to modify the script to use 3 server or 2 server environment, as long as Search has never been configured on your Farm or was configured and now removed.

Let’s understand the script on a piecemeal basis:

Section 1: setting up the environment and gather user inputs on Server Names, load SharePoint snap-in, managed account to use etc

 Set-ExecutionPolicy unrestricted
 Clear-Host
  
 # Start Loading SharePoint Snap-in
 $snapin = (Get-PSSnapin -name Microsoft.SharePoint.PowerShell -EA SilentlyContinue)
 IF ($snapin -ne $null){
 write-host -f Green "SharePoint Snap-in is loaded... No Action taken"}
 ELSE  {
 write-host -f Yellow "SharePoint Snap-in not found... Loading now"
 Add-PSSnapin Microsoft.SharePoint.PowerShell
 write-host -f Green "SharePoint Snap-in is now loaded"}
 # END Loading SharePoint Snapin
  
 $hostA = Get-SPEnterpriseSearchServiceInstance -Identity "SP13App"
 $hostB = Get-SPEnterpriseSearchServiceInstance -Identity "SP13-App2"
 $hostC = Get-SPEnterpriseSearchServiceInstance -Identity "SP13WFE01"
 $hostD = Get-SPEnterpriseSearchServiceInstance -Identity "SP13WFE02"
  
 $searchName = "Fabricam Search Service"
 $searchDB = "SP_Services_Search_DB"
 $searchAcct = "fabricam\spService"
 $searchAcctCred = convertto-securestring "pass@word1" -asplaintext -force
 $searchManagedAcct = Get-SPManagedAccount | Where {$_.username-eq 'fabricam\spService'}
 $searchAppPoolName = "Search Services Application Pool"
 IF((Get-spserviceapplicationPool | Where {$_.name -eq "Search Services Application Pool"}).name -ne "Search Services Application Pool"){
 $searchAppPool = New-SPServiceApplicationPool -Name $searchAppPoolName -Account $searchManagedAcct} 
  

Section 2: Starting Search Service on all servers. You will notice there are some error handling in this script, for example, instead of just firing off the commands, I am actually waiting for the Search Service to respond before I go over to the next step. I have always found this approach very stable.

  
 ## Start Search Service Instances
 Write-Host "Starting Search Service Instances..."
 # Server 1
 IF((Get-SPEnterpriseSearchServiceInstance -Identity $hostA).Status -eq 'Disabled'){
 Start-SPEnterpriseSearchServiceInstance -Identity $hostA 
 Write-Host "Starting Search Service Instance on" $hostA.Server.Name
 Do { Start-Sleep 5;
 Write-host -NoNewline "."  } 
 While ((Get-SPEnterpriseSearchServiceInstance -Identity $hostA).Status -eq 'Online')
 Write-Host -ForegroundColor Green "Search Service Instance Started on" $hostA.Server.Name
 } ELSE { Write-Host -f Green "Search Service Instance is already running on" $hostA.Server.Name  }
  
 #Server 2
 IF((Get-SPEnterpriseSearchServiceInstance -Identity $hostB).Status -eq 'Disabled'){
 Start-SPEnterpriseSearchServiceInstance -Identity $hostB 
 Write-Host "Starting Search Service Instance on" $hostB.Server.Name
 Do { Start-Sleep 5;
 Write-host -NoNewline "."  } 
 While ((Get-SPEnterpriseSearchServiceInstance -Identity $hostB).Status -eq 'Online')
 Write-Host -ForegroundColor Green "Search Service Instance Started on" $hostB.Server.Name
 } ELSE { Write-Host -f Green "Search Service Instance is already running on" $hostB.Server.Name  }
   
 #Server 3
 IF((Get-SPEnterpriseSearchServiceInstance -Identity $hostC).Status -eq 'Disabled'){
 Start-SPEnterpriseSearchServiceInstance -Identity $hostC 
 Write-Host "Starting Search Service Instance on" $hostC.Server.Name
 Do { Start-Sleep 5;
 Write-host -NoNewline "."  } 
 While ((Get-SPEnterpriseSearchServiceInstance -Identity $hostC).Status -eq 'Online')
 Write-Host -ForegroundColor Green "Search Service Instance Started on" $hostC.Server.Name
 } ELSE { Write-Host -f Green "Search Service Instance is already running on" $hostC.Server.Name  }
  
 #Server 4
 IF((Get-SPEnterpriseSearchServiceInstance -Identity $hostD).Status -eq 'Disabled'){
 Start-SPEnterpriseSearchServiceInstance -Identity $hostD 
 Write-Host "Starting Search Service Instance on" $hostD.Server.Name
 Do { Start-Sleep 5;
 Write-host -NoNewline "."  } 
 While ((Get-SPEnterpriseSearchServiceInstance -Identity $hostD).Status -eq 'Online')
 Write-Host -ForegroundColor Green "Search Service Instance Started on" $hostD.Server.Name
 } ELSE { Write-Host -f Green "Search Service Instance is already running on" $hostD.Server.Name  }
  

Section 3: Starting the Search Query and Site Setting Service Instance on Application Servers. If you don’t wait for a response from Search Service on Application Servers in the step above and try to run this step, it’s very likely that it would fail.

Additional Reference: https://msdn.microsoft.com/en-us/library/office/microsoft.office.server.search.administration.searchqueryandsitesettingsservice.aspx

This service provides the creation of a SearchServiceApplication or a SearchServiceApplicationProxy to a Search service application. This allows the caller to establish effective load balancing of Search queries across query servers.

 
 ## Start Query and Site Settings Service Instance
 Write-Host "
 Starting Search Query and Site Settings Service Instance on" $hostA.server.Name "and" $hostB.server.Name
 Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance $hostA.server.Name
 Do { Start-Sleep 3;
 Write-host -NoNewline "."  } 
 While ((Get-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance | Where {$_.Server.Name -eq $hostA.server.Name}).status -ne 'Online')
 Write-Host -ForegroundColor Green "
     Query and Site Settings Service Instance Started on" $hostA.Server.Name
  
 Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance $hostB.server.Name
 Do { Start-Sleep 3;
 Write-host -NoNewline "."  } 
 While ((Get-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance | Where {$_.Server.Name -eq $hostB.server.Name}).status -ne 'Online')
 Write-Host -ForegroundColor Green "
     Query and Site Settings Service Instance Started on" $hostB.Server.Name 

 

Section 4: Create the Search Service Application

 
 ## Create Search Service Application
 Write-Host "
 Creating Search Service Application..."
  
 $searchAppPool = Get-SPServiceApplicationPool -Identity "Search Services Application Pool"
  
 IF ((Get-SPEnterpriseSearchServiceApplication).Status -ne 'Online'){
 Write-Host " Provisioning. Please wait..."
 $searchApp = New-SPEnterpriseSearchServiceApplication -Name $searchName -ApplicationPool $searchAppPool -AdminApplicationPool $searchAppPool -DatabaseName $searchDB
 DO {start-sleep 2;
 write-host -nonewline "." } While ( (Get-SPEnterpriseSearchServiceApplication).status -ne 'Online')
 Write-Host -f green " 
     Provisioned Search Service Application"
 } ELSE {  write-host -f green "Search Service Application already provisioned."
 $searchApp = Get-SPEnterpriseSearchServiceApplication
 } 

Section 5: creating the Admin Component. Initial Search Topology is created with this as well.

 
 ## Set Search Admin Component
 Write-Host "Set Search Admin Component..."
 $AdminComponent = $searchApp | Get-SPEnterpriseSearchAdministrationComponent | Set-SPEnterpriseSearchAdministrationComponent -SearchServiceInstance $hostA 

Section 6: get the Initial Search Topology and Clone it

 ## Get Initial Search Topology
 Write-Host "Get Initial Search Topology..."
 $initialTopology = Get-SPEnterpriseSearchTopology -SearchApplication $searchApp
  
 ## Create Clone Search Topology
 Write-Host "Creating Clone Search Topology..."
 $cloneTopology = New-SPEnterpriseSearchTopology -SearchApplication $searchApp -Clone -SearchTopology $initialTopology 

 

Section 7: here is where we define where different Search Components will live. We want to create a redundant topology for load balancing and high availability. As long as same services are running on multiple servers, SharePoint will use its internal Load Balancer.

We will deploy Admin Component, Crawl Component, Analytics Processing Component, Content Processing Component and Index Partition 0 on both the Application Servers and we will run Query Processing Component on both the Web Front End Servers.

If you are new these components mentioned above, refer to this TechNet Article .

 
 ## Host-A Components
  
 Write-Host "Creating Host A Components (Admin, Crawl, Analytics, Content Processing, Index Partition)..."
  
 $AdminTopology = New-SPEnterpriseSearchAdminComponent -SearchServiceInstance $hostA -SearchTopology $cloneTopology
 $CrawlTopology = New-SPEnterpriseSearchCrawlComponent -SearchServiceInstance $hostA -SearchTopology $cloneTopology
 $AnalyticsTopology = New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchServiceInstance $hostA -SearchTopology $cloneTopology
 $ContentProcessingTopology = New-SPEnterpriseSearchContentProcessingComponent -SearchServiceInstance $hostA -SearchTopology $cloneTopology
 $IndexTopology = New-SPEnterpriseSearchIndexComponent -SearchServiceInstance $hostA -SearchTopology $cloneTopology -IndexPartition 0
  
 ## Host-B Components
  
 Write-Host "Creating Host B Components (Admin, Crawl, Analytics, Content Processing, Index Partition)..."
  
 $AdminTopology = New-SPEnterpriseSearchAdminComponent -SearchServiceInstance $hostB -SearchTopology $cloneTopology
 $CrawlTopology = New-SPEnterpriseSearchCrawlComponent -SearchServiceInstance $hostB -SearchTopology $cloneTopology
 $AnalyticsTopology = New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchServiceInstance $hostB -SearchTopology $cloneTopology
 $ContentProcessingTopology = New-SPEnterpriseSearchContentProcessingComponent -SearchServiceInstance $hostB -SearchTopology $cloneTopology
 $IndexTopology = New-SPEnterpriseSearchIndexComponent -SearchServiceInstance $hostB -SearchTopology $cloneTopology -IndexPartition 0
  
 ## Host-C Components
  
 Write-Host "Creating Host C Components (Query)..."
  
 $QueryTopology = New-SPEnterpriseSearchQueryProcessingComponent -SearchServiceInstance $hostC -SearchTopology $cloneTopology
  
 ## Host-D Components
  
 Write-Host "Creating Host D Components (Query)..."
  
 $QueryTopology = New-SPEnterpriseSearchQueryProcessingComponent -SearchServiceInstance $hostD -SearchTopology $cloneTopology

Section 8: Next we will activate the new topology that we just created above and remove the initial Search topology which should be in “Inactive” State.

 ## Activate Clone Search Topology
 Write-Host "Activating Clone Search Topology...Please wait. This will take some time"
 Set-SPEnterpriseSearchTopology -Identity $cloneTopology
  
 ## Remove Initial Search Topology
 Write-Host "Removing Initial Search Topology..."
 $initialTopology = Get-SPEnterpriseSearchTopology -SearchApplication $searchApp | where {($_.State) -eq "Inactive"}
 Remove-SPEnterpriseSearchTopology -Identity $initialTopology -Confirm:$false 

Section 9: Last step is to create the Search Service Application Proxy

 ## Create Search Service Application Proxy
 Write-Host "Creating Search Service Application Proxy..."
 $searchAppProxy = New-SPEnterpriseSearchServiceApplicationProxy -Name "$searchName Proxy" -SearchApplication $searchApp

And here is the end result:

Here are the services running on all servers:

clip_image002[5]

And here is the topology:

clip_image004

Cheers!

Priyo

Note: The referenced PowerShell script is attached to this post. Use at your own risk, modify to meet the parameters of your own environment, and test before using in production!

Provision Search.ps1