Creating and configure a SharePoint 2013 Enterprise Search Service Application with a two-tier topology

SharePoint 2013 Enterprise Search is a major feature of SharePoint 2013, however the topology must be set in PowerShell which can present a challenge.  To address this, I have written a script that will create the application and its dependencies and create a two-tier search topology. 

The tiers are "Search Front End" which servers user queries and store the index and "Search Back End" which crawl and host the administration components.  The machinery is in place to add additional tiers if desired, just add in a new variable with server names and replicate a foreach() block in the "#Build and Set the Topology" section and adjust the services that should run on each tier.

The script will prompt for credentials that should be used for the Default Content Access Account.  Additionally, the managed account that the Search Service Application pool will run under must be a previously-configured managed account.

#Add SharePoint PowerShell snap-in
Add-PSSnapin microsoft.sharepoint.powershell

##### Set Local Variables
#Search Application Pool Name
$SearchAppPoolName = "SearchServicePool"
#Search Application Pool Account, must be a previously registered managed account
$SearchAppPoolAccount = “CONTOSO\account”
#Crawl Account Name
$CrawlAccount = Get-Credential -Message "Default Content Access Account Credentials"
#Search Service Application Name
$SearchAppName = "Search Service Application"
#Search Service Application Proxy Name
$SearchProxy = "$SearchAppName Proxy"
#Database Server that hosts the application
$DBServer = "SQL\instance"
#Root Database Name for Search Service Application
$DBName = "SP_Search"
#Drive Path where SharePoint should store the Search Index, must already exist.
$Indexlocation = “I:\Index”
#Search Front End Server List, separate each server with a comma.
$SearchFrontEnds = "Server1", "Server2”
#Search Application Servers List
$SearchAppSrvs = "Server1", "Server2”
#Get Application Pool for Search Administration Service, must already exist.
$AdminAppPool = Get-SPServiceApplicationPool -Identity "SearchServicePool"
#####

#Create Search Application Pool
"Provisioning Search Application Pool...” | Write-Host
$AppPool = New-SPServiceApplicationPool -Name $SearchAppPoolName -Account $SearchAppPoolAccount

#Start the search service instances on each of the search servers
"Starting Search Service Instances...” | Write-Host
foreach($ServerName in $SearchFrontEnds){
      Start-SPEnterpriseSearchServiceInstance -Identity $ServerName
      Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance -Identity     $ServerName
      }
foreach($ServerName in $SearchAppSrvs){
      Start-SPEnterpriseSearchServiceInstance -Identity $ServerName
      Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance -Identity     $ServerName
      }

#Wait for the Services to provision 
while(Get-SPEnterpriseSearchServiceInstance | ?{$_.status -eq "Provisioning"}){
      start-sleep 2
      }
#Confirm that everything provisioned correctly by cycling through the search servers and ensuring that the Search Service Instance is “Online”
foreach($ServerName in $SearchFrontEnds){
      if(!((Get-SPEnterpriseSearchServiceInstance -Identity $ServerName).status -eq "Online")){
            throw(“The Search Instance on $ServerName failed to provision.  Run Get-SPEnterpriseSearchServiceInstance to view the status of all Search Service Instances”)
            }
      }
foreach($ServerName in $SearchAppSrvs){
      if(!((Get-SPEnterpriseSearchServiceInstance -Identity $ServerName).status -eq "Online")){
            throw(“The Search Instance on $ServerName failed to provision.  Run Get-SPEnterpriseSearchServiceInstance to view the status of all Search Service Instances”)
            }
      }
"Search Instances Provisioned`n” | Write-Host

#Create Search Service Application and Application Proxy in SharePoint
"Provisioning Search Service Application and Proxy..." | Write-Host
New-SPEnterpriseSearchServiceApplication -Name $SearchAppName -ApplicationPool $SearchAppPoolName -DatabaseName $DBName -AdminApplicationPool $AdminAppPool
Start-Sleep 10
#Create Search Service Application and Proxy
New-SPEnterpriseSearchServiceApplicationProxy -Partitioned -Name $SearchProxy -SearchApplication $SearchAppName
Start-Sleep 10
Set-SPEnterpriseSearchServiceApplication -Identity $SearchAppName -DefaultContentAccessAccountName $CrawlAccount.Username -DefaultContentAccessAccountPassword $CrawlAccount.Password
$SearchServiceApp = Get-SPEnterpriseSearchServiceApplication -Identity $SearchAppName

##### Build and Set the Topology
#Create the Topology Object
"Building Search Topology...” | Write-Host
$newTopology = New-SPEnterpriseSearchTopology -SearchApplication $SearchServiceApp

#Define Search Front End Topology
foreach($ServerName in $SearchFrontEnds){
     $ServerInstance = Get-SPEnterpriseSearchServiceInstance -Identity $ServerName
     New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $ServerInstance
     New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $ServerInstance -RootDirectory $IndexLocation -IndexPartition 0
     }

#Define Search Application Server Topology
foreach($ServerName in $SearchAppSrvs){
     $ServerInstance = Get-SPEnterpriseSearchServiceInstance -Identity $ServerName
     New-SPEnterpriseSearchAdminComponent -SearchTopology $newTopology -SearchServiceInstance $ServerInstance
     New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopology -SearchServiceInstance $ServerInstance
     New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $ServerInstance
     New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $ServerInstance
     }

#Set the Topology
"Setting Topology..." | Write-Host
Start-Sleep 2
Set-SPEnterpriseSearchTopology -Identity $newTopology
"All Done,`nCheck the Search Administration page in Central Administration to verify” | Write-Host