Create and Provision a Search Service Application With Powershell

Here is a Cool Script to Create and Provision a new Search Service Application in SharePoint 2010 using PowerShell.  If you split the roles between servers, you can put (example : $querysever = ” WFE1″

Here is the script.  If you have any questions, do not hesitate. Say thanks if it helped 🙂

$ErrorActionPreference = “Stop”

Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0

function ConfigureSharePointSearch(

    [Microsoft.SharePoint.Administration.SPIisWebServiceApplicationPool] $appPool,

    [System.Management.Automation.PSCredential] $crawlCredentials,    

    [string] $serviceAppName = “Search Service Application”,

    [string] $searchDatabaseName = “SearchService”,

    [string] $searchServer = $env:COMPUTERNAME,

    [string] $adminServer = $env:COMPUTERNAME,

    [string] $crawlServer = $env:COMPUTERNAME,

    [string] $queryServer = $env:COMPUTERNAME)

{

    Write-Host “Configuring SharePoint Search…”

    Write-Host “appPool: $appPool”

    Write-Host “crawlCredentials: $($crawlCredentials.Username)”

    Write-Host “serviceAppName: $serviceAppName”

    Write-Host “searchDatabaseName: $searchDatabaseName”

    Write-Host “searchServer: $searchServer”

    Write-Host “adminServer: $adminServer”

    Write-Host “crawlServer: $crawlServer”

    Write-Host “queryServer: $queryServer”

    If ($appPool -eq $null)

    {

        Throw “The application pool must be specified.”

    }

    ElseIf ($crawlCredentials -eq $null)

    {

        Throw “The crawl credentials must be specified.”

    }

    Write-Host “Creating $serviceAppName…”

    $searchApp = New-SPEnterpriseSearchServiceApplication -Name $serviceAppName `

        -ApplicationPool $appPool -DatabaseName $searchDatabaseName -Debug:$false

    Write-Host (“Starting the SharePoint Search Service instance and Search Admin” `

        + ” component…”)

    $adminSearchInstance = Get-SPEnterpriseSearchServiceInstance -Debug:$false |

        Where { $_.Server -match $adminServer }

    $admin = $searchApp |

        Get-SPEnterpriseSearchAdministrationComponent -Debug:$false

    if($adminSearchInstance.Status -ne “Online”)

    {

        Write-Host “Provisioning SharePoint Search Service instance…”

        $adminSearchInstance.Provision()

        Start-Sleep 10

    }

    $admin | Set-SPEnterpriseSearchAdministrationComponent `

        -SearchServiceInstance $adminSearchInstance -Debug:$false

    $admin = ($searchApp | Get-SPEnterpriseSearchAdministrationComponent `

        -Debug:$false)

    Write-Host -NoNewLine “Waiting for Search Admin component to initialize…”

    While (-not $admin.Initialized) 

    {

        Write-Host -NoNewLine “.”

        Start-Sleep -Seconds 5

        $admin = $searchApp |

            Get-SPEnterpriseSearchAdministrationComponent -Debug:$false

    }

    Write-Host

    Write-Host “Setting the default content access account…”

    $searchApp | Set-SPEnterpriseSearchServiceApplication `

        -DefaultContentAccessAccountName $crawlCredentials.Username `

        -DefaultContentAccessAccountPassword $crawlCredentials.Password `

        -Debug:$false

    Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance $adminServer `

        -Debug:$falseservice

    Write-Host “Getting initial topologies…”

    $initialCrawlTopology = $searchApp |

        Get-SPEnterpriseSearchCrawlTopology -Debug:$false

    $initialQueryTopology = $searchApp |

        Get-SPEnterpriseSearchQueryTopology -Debug:$false

    Write-Host “Creating new crawl topology…”

    $crawlTopology = $searchApp |

        New-SPEnterpriseSearchCrawlTopology -Debug:$false

    $crawlDatabase = Get-SPEnterpriseSearchCrawlDatabase `

        -SearchApplication $searchApp -Debug:$false

    Write-Host “Populating new crawl topology…”

    $crawlInstance = Get-SPEnterpriseSearchServiceInstance -Debug:$false |

        Where { $_.Server -match $crawlServer }

    $crawlComponent = New-SPEnterpriseSearchCrawlComponent `

        -CrawlTopology $crawlTopology -CrawlDatabase $crawlDatabase `

        -SearchServiceInstance $crawlInstance -Debug:$false

    Write-Host “Activating new crawl topology…”

    $crawlTopology | Set-SPEnterpriseSearchCrawlTopology -Active -Debug:$false

    $initialCrawlTopology.CancelActivate()

    Write-Host -NoNewLine “Waiting for initial crawl topology to be inactive…”

    Do

    {

        Start-Sleep 5

        Write-Host -NoNewLine “.”

    } While ($initialCrawlTopology.State -ne “Inactive”)

    Write-Host

    Write-Host “Creating new query topology…”

    $queryTopology = $searchApp |

        New-SPEnterpriseSearchQueryTopology -Partitions 1 -Debug:$false

    Write-Host “Creating Property Store database…”

    $propertyDatabase = Get-SPEnterpriseSearchPropertyDatabase `

        -SearchApplication $searchApp -Debug:$false

    Write-Host “Setting index partition to use Property Store database…”

    $indexPartition = Get-SPEnterpriseSearchIndexPartition `

        -QueryTopology $queryTopology -Debug:$false

    $indexPartition | Set-SPEnterpriseSearchIndexPartition `

        -PropertyDatabase $propertyDatabase -Debug:$false

    Write-Host “Populating new query topology….”

    $queryInstance = Get-SPEnterpriseSearchServiceInstance -Debug:$false |

        Where { $_.Server -match $queryServer }

    $queryComponent = New-SPEnterpriseSearchQueryComponent `

        -QueryTopology $queryTopology -IndexPartition $indexPartition `

        -SearchServiceInstance $queryInstance -Debug:$false

    Write-Host “Activating new query topology…”

    $QueryTopology | Set-SPEnterpriseSearchQueryTopology -Active -Debug:$false

    Write-Host -NoNewLine “Waiting for initial query topology to be inactive…”

    Do

    {

        Start-Sleep 5

        Write-Host -NoNewLine “.”

    } While ($initialQueryTopology.State -ne “Inactive”)

    Write-Host

    Write-Host “Removing initial topologies…”

    $initialCrawlTopology |

        Remove-SPEnterpriseSearchCrawlTopology -Confirm:$false -Debug:$false

    $initialQueryTopology |

        Remove-SPEnterpriseSearchQueryTopology -Confirm:$false -Debug:$false

    Write-Host “Creating service application proxy…”

    $searchProxy = New-SPEnterpriseSearchServiceApplicationProxy `

        -Name “$serviceAppName” -SearchApplication $searchApp -Debug:$false

    Write-Host -Fore Green “Successfully configured SharePoint Search.”

}

function GetServiceAppsAppPool(

    [string] $appPoolName,

    [string] $appPoolUserName)

{

    Write-Debug “Trying to get existing service application pool ($appPoolName)…”

    $appPool = Get-SPServiceApplicationPool $appPoolName -Debug:$false -EA 0

    If ($appPool -ne $null)

    {

        Write-Debug “The service application pool ($appPoolName) already exists.”

        return $appPool

    }

    Write-Host “Creating service application pool ($appPoolName)…”

    Write-Debug “Get service account for application pool ($appPoolUserName)…”

    $appPoolAccount = Get-SPManagedAccount -Identity $appPoolUserName `

        -Debug:$false -EA 0

    If($appPoolAccount -eq $null)

    {

        Write-Host “Registering managed account ($appPoolUserName)…”

        Write-Debug “Get credential ($appPoolUserName)…”

        $appPoolCredential = Get-Credential $appPoolUserName

        $appPoolAccount =

            New-SPManagedAccount -Credential $appPoolCredential -Debug:$false

    } 

    If ($appPoolAccount -eq $null)

    {

        Write-Host -Force Red (“Unable to find or create the managed account” `

            + ” ($appPoolUserName).”)

        Exit 1

    }

    $appPool = New-SPServiceApplicationPool -Name $appPoolName `

        -Account $appPoolAccount -Debug:$false

    Write-Host -Fore Green (“Successfully created service application pool” `

        + ” ($appPoolName).”)

    return $appPool

}

function ValidateCredentials(

    $credentials)

{

    Write-Debug “Validating credentials ($($credentials.UserName))…”

    $password = [Runtime.InteropServices.Marshal]::PtrToStringAuto(

        [Runtime.InteropServices.Marshal]::SecureStringToBSTR(

            $credentials.Password))

    $currentDomain = “LDAP://” + ([ADSI]””).distinguishedName

    $domain = New-Object DirectoryServices.DirectoryEntry(

        $currentDomain,

        $credentials.UserName,

        $password)

    trap { $script:err = $_ ; continue } &{

        $domain.Bind($true); $script:err = $null }

    if ($err.Exception.ErrorCode -ne -2147352570)

    {

        Write-Host -Fore Red $err.Exception.Message

        Exit 1

    }

    Write-Debug “Successfully validated credentials ($($credentials.UserName)).”

}

function Main()

{

    $searchServer = $env:COMPUTERNAME

    $adminServer = $searchServer

    $crawlServer = $searchServer

    $queryServer = $searchServer

    $serviceAppsAppPoolName = “SharePoint Service Applications”

    $serviceAppsAppPoolUserName = $env:USERDOMAIN + “sppool”

    $serviceAppName = “Search Service Application”

    $searchDatabaseName = “”

    $crawlServiceAccount = $env:USERDOMAIN + “spcrawl”

    Write-Host (“Please enter the password for the default content access account” `

        + ” ($crawlServiceAccount)…”)

    $crawlCredentials = Get-Credential $crawlServiceAccount

    ValidateCredentials $crawlCredentials

    $appPool = GetServiceAppsAppPool $serviceAppsAppPoolName `

        $serviceAppsAppPoolUserName

    ConfigureSharePointSearch $appPool $crawlCredentials $serviceAppName `

        $searchDatabaseName $searchServer $adminServer $crawlServer $queryServer

}

Main