For those who don’t know, SharePoint Foundation 2013 only allows you to create Search Service Application with the built-in Wizard from the Central Admin GUI. The drawback is the trailing guid’s at the end of the database names that end up in your SQL server instance.
And this is what you get when you try to use PowerShell to create the Search Service Application in SharePoint Foundation 2013:
NOTE: If you don’t understand this well, please do not attempt to run this script. Microsoft will probably not support your farm or search application built this way.
A very BIG Thank you note to Gary Lapointe for his post here. I took his script a bit further and tweaked it to use custom DB names and further create the default topology using reflection in PowerShell.
We are going to take a deeper look with .Net Reflector behind the scenes to identify which functions we need to call and what parameters they use.
Browse the Microsoft.Office.Server.Search.dll via reflector (In case you are wondering you can check the location of this dll in the below screenshot)
Now we are going to navigate to the node where the functions are stored for creating Search Service Application. For this we need to traverse to Microsoft.Office.Server.Search.Administration – SearchService
As you can see in the above screenshot, there are several functions named CreateApplication. The one which we are interested in is this one:
public
SearchServiceApplication
CreateApplication(string name, SPDatabaseParameters adminDBParameters, SPDatabaseParameters propertyStoreDBParameters, SPDatabaseParameters crawlStoreDBParameters, SPDatabaseParameters analyticsReportingStoreDBParameters, SPDatabaseParameters linksStoreDBParameters, SPIisWebServiceApplicationPool applicationPool, SPIisWebServiceApplicationPool adminApplicationPool)
This function will allow us to provide our own DB name parameters.
However, this function will create the Service Application only. We still need a way to create the default topology. So in order to not having go through the entire process of creating each topology components manually via reflection, I took a deep dive into the function which SPF wizard calls internally i.e. CreateApplicationWithDefaultTopology(). Looking into this function I found the internal function it uses to create the default topology all by itself. Let us take a look in reflection:
So now that we have both our functions identified from reflection, all we have to do is write the PowerShell script.
Here it is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#Start the search service instance on the server Start-SPEnterpriseSearchServiceInstance $env:computername Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance $env:computername #Give a unique name to your search service application $serviceAppName = "MyCleanDB Search Service Application" #Get the application pools to use (make sure you change the value for your environment) $svcPool = Get-SPServiceApplicationPool "SharePoint Web Services Default" $adminPool = Get-SPServiceApplicationPool "SharePoint Web Services Default" #Get the service from the service instance so we can call a method on it $searchServiceInstance = Get-SPEnterpriseSearchServiceInstance βLocal $searchService = $searchServiceInstance.Service #Define your unique DB names without the guids $adminDB = "Search_Service_Application_DB" $propertyStoreDB = "Search_Service_Application_PropertyStoreDB" $crawlStoreDB = "Search_Service_Application_CrawlStoreDB" $analysticsStoreDB = "Search_Service_Application_AnalyticsStoreDB" $linkStoreDB = "Search_Service_Application_LinkStoreDB" #Since this method takes in the value of object type Microsoft.SharePoint.Administration.SPDatabaseParameters we will create these from our clean DB names $adminDBParameters = [Microsoft.SharePoint.Administration.SPDatabaseParameters]::CreateParameters($adminDB,"None") $propertyDBParameters = [Microsoft.SharePoint.Administration.SPDatabaseParameters]::CreateParameters($propertyStoreDB,"None") $crawlStoreDBParameters = [Microsoft.SharePoint.Administration.SPDatabaseParameters]::CreateParameters($crawlStoreDB,"None") $analyticsStoreDBParameters = [Microsoft.SharePoint.Administration.SPDatabaseParameters]::CreateParameters($analysticsStoreDB,"None") $linkStoreDBParameters = [Microsoft.SharePoint.Administration.SPDatabaseParameters]::CreateParameters($linkStoreDB,"None") #Create the search service application by calling the function $searchServiceApp = $searchService.CreateApplication($serviceAppName, $adminDBParameters, $propertyDBParameters, $crawlStoreDBParameters, $analyticsStoreDBParameters, $linkStoreDBParameters, [Microsoft.SharePoint.Administration.SPIisWebServiceApplicationPool]$svcPool, [Microsoft.SharePoint.Administration.SPIisWebServiceApplicationPool]$adminPool) #Create the search service application proxy as usual (luckily PowerShell for this works and is bot blocked) $searchProxy = New-SPEnterpriseSearchServiceApplicationProxy -Name "$serviceAppName Proxy" -SearchApplication $searchServiceApp #Provision the search service application $searchServiceApp.Provision() |
At this point the search service application will be provisioned without any topology components.
1 2 3 4 5 6 7 8 |
#Get an updated handle on the SearchServiceInstance $searchServiceInstance = Get-SPEnterpriseSearchServiceInstance βLocal #Now we will call the method to initiate the default topology component creation using reflection $bindings = @("InvokeMethod", "NonPublic", "Instance") $types = @([Microsoft.Office.Server.Search.Administration.SearchServiceInstance]) $values = @([Microsoft.Office.Server.Search.Administration.SearchServiceInstance]$searchServiceInstance) $methodInfo = $searchServiceApp.GetType().GetMethod("InitDefaultTopology", $bindings, $null, $types, $null) $searchTopology = $methodInfo.Invoke($searchServiceApp, $values) |
Now you need some patience while all the components spring to life behind the scenes. This can take some time depending how robust your environment is. After a while you will have your search provisioned with clean DBs as shown below:
Happy SharePointing !!
PS: I will be speaking at the biggest SharePoint online conference www.SP24Conf.com on multitenancy where I will show how to create this search application in partitioned mode for use in multitenant environment.
You are awesome, well done on doing this.
Great post Jasjit! Helped me a lot. Thanks.
Thanks Robert, glad it helped.
Great script; thanks for doing the digging!
Thanks Kyle
Hi Jasjit Chopra
must i run the second script to?
“#Get an updated handle on the SearchServiceInstance
$searchServiceInstance = Get-SPEnterpriseSearchServiceInstance βLocal
#Now we will call the method to initiate the default topology component creation using reflection
$bindings = @(“InvokeMethod”, “NonPublic”, “Instance”)
$types = @([Microsoft.Office.Server.Search.Administration.SearchServiceInstance])
$values = @([Microsoft.Office.Server.Search.Administration.SearchServiceInstance]$searchServiceInstance)
$methodInfo = $searchServiceApp.GetType().GetMethod(“InitDefaultTopology”, $bindings, $null, $types, $null)
$searchTopology = $methodInfo.Invoke($searchServiceApp, $values)”
regards
Tommy
Yes it is required or else your topology will be empty
I’m getting an error on this line.
$methodInfo = $searchServiceApp.GetType().GetMethod(βInitDefaultTopologyβ, $bindings, $null, $types, $null)
the error is something like i can’t call the method with $null value.
ideas? π
Can you paste the exact description of the error? Also which patch version of SP 2013 are you on ?
Hello Christian,
I think you called the 2nd Part in a separate ps1 file?
Then you have no value for ” $searchServiceApp”, which is defined in Part 1 of the script.
I assume you have to paste poth parts into one single script and execute it, so that the value for ” $searchServiceApp” is filled.
Am I right, Jasjit?
Kind Regrads
Yes you are correct – it is a continuation of the same script….
You need to put it in one ps1 for automation or execute the commands in one powershell window one by one.
A lifesaver thanks a lot!!
Glad it could help!
Hi, We have a SharePoint Foundation 2013 with SP1 Environment.
In that, we have 2 Front-End Servers and 2 App Servers. In the Front-End Servers, the Search Service is stopped and is in Disabled state and in the 2 App Servers in One App Server, Search is Online and in another Search is Starting but goes to Stopped soon after.
Originally, we had only 1 App Server and we were running our Search Service and Search Service Application in that. Now since the index location became full and we were unable to increase the drive there, we added one more App Server and now the issue is Search is not properly getting configured in either of these App servers. What we want to do is run Search only in the new App Server, because we have a lot of storage space for Index locations here, but in the older App Server, not run Search at all. We tried keeping the Search Service disabled and ran the below PowerShell Scripts, but none of the ones are working. These scripts are creating the Search Service Application, but the error of “Admin Component is not Online”, “Could not connect to the machine hosting SharePoint 2013 admin component” is coming up.
I did follow steps in this blog, but of no positive results. Would greatly appreciate if I can get some guidance on getting this fixed please.
Just delete your existing search service and then use my script. It should work
Hello Jasjit,
This script was the only solution, that helped me to get rid of “Getting results failed: Microsoft.Office.Server.Search.Query.InternalQueryErrorException” error, whilst trying to use Enterprise Search on SharePoint Foundation 2013 in Dynamics AX 2012 R2.
Thank you!
Glad it could help !
Thank you for this post! I’ve been trying to re-provision Search on our Foundations 2013 all day.
You are welcome π
Hi…
Same issue as Cristian… here is the error…
PS C:\Temp> $searchServiceInstance = Get-SPEnterpriseSearchServiceInstance -Local
PS C:\Temp> $bindings = @(“InvokeMethod”, “NonPublic”, “Instance”)
PS C:\Temp> $types = @([Microsoft.Office.Server.Search.Administration.SearchServiceInstance])
PS C:\Temp> $values = @([Microsoft.Office.Server.Search.Administration.SearchServiceInstance]$searchServiceInstance)
PS C:\Temp> $methodInfo = $searchServiceApp.GetType().GetMethod(“InitDefaultTopology”, $bindings, $null, $types, $null)
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $methodInfo = $searchServiceApp.GetType().GetMethod(“InitDefaultTopology”, $bind …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Thanks for your help
Francis
Simply run all the script in one session or one powershell script file. Running the second part on its own will have this error. It is relying on variables form the above section.
i have execute just the script, now i have the problem that i could excute the script with additional topology settings… please could someone help me?
You are Gold …
Thank you so very much for posting this one
Glad it helped π
when i run the following command
$searchServiceApp = $searchService.CreateApplication($serviceAppName, $adminDBParameters, $propertyDBParameters, $crawlStoreDBParameters, $analyticsStoreDBParameters, $linkStoreDBParameters, [Microsoft.SharePoint.Administration.SPIisWebServiceApplicationPool]$svcPool, [Microsoft.SharePoint.Administration.SPIisWebServiceApplicationPool]$adminPool)
i get the following error
Exception calling “CreateApplication” with “8” argument(s): “Value cannot be
null.
Parameter name: databaseParameters”
At line:1 char:1
+ $searchServiceApp = $searchService.CreateApplication($serviceAppName,
$adminDBPa …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentNullException
can you give any suggestions?
Hi Ben,
You need to the run the script in continuation. They are not separate scripts but continuation of the same.
Regards,
Jasjit
hi, unfortunately this did not help me, the second part run without problem but default topology was not cretaed
Actually now I can see using Get-SPEnterpriseSearchServiceApplication that topology created but UI still shows the error you have in the screenshot
Sorry for the late reply but you just need to execute the full script and wait and make sure timer job service is running.
Thanks for for the script, i have been trying to get this to work for a while now.
You are welcome! Glad it helped π
Hello Jasjit Chopra,
Thanks a million for your great script. I tried it out and it worked perfectly π I have 2 WFEs, 2 Apps and 1 SQL in the farm. Now search is running on App1 server, I’d like to add search on App2 server too (App2 already joined into the existing farm) for HA (if each App server is down, search still works)
So please show me how to customise the script to do that
Looking forward to hearing from you soon
Many thanks,
I am really glad this could be helpful to you.
However since this is SP Foundation it does not allow scalability. Search can only run on one server.
Hello Jasjit Chopa,
Many thanks for your reply. So you mean that foundation doesn’t support scalability for search only ? Or everything ? (E.g. How about load balancing for 2 wfes)
Thanks,
Khoa
Hey! Awesome work! Is there also an Option to add a index location? i know that SP Standard got this but im not very familiar with foundation :S
Hi Daniel,
Glad it could help. I have not looked into the index part yet. I will see if I can get the time to find that via powershell and update it here.
Regards,
Jasjit
Awesome…Great script ..Thanks Jasjit
You are welcome !
Hi,
Do I Need to change the computername or other variables in the Script according to my environment??
Not for the computer environment – but you should look into the DB names and service application variables for sure.
How long it takes to execute both part of script completely?
Depends on the back-end horsepower of your systems. After you have run these scripts I suggest you wait for some time have patience and all the components will come alive in SP Search Admin center.
Im getting the following when running the script:
Exception calling “CreateApplication” with “8” argument(s): “The timer job did not complete running within the allotted time.”
At C:\Scripts\create-search.ps1:31 char:1
+ $searchServiceApp = $searchService.CreateApplication($serviceAppName, …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : TimeoutException
New-SPEnterpriseSearchServiceApplicationProxy : Cannot bind argument to parameter ‘SearchApplication’ because it is null.
At C:\Scripts\create-search.ps1:34 char:111
+ … xy -Name “$serviceAppName Proxy” -SearchApplication $searchServiceApp
You need to run the complete script in one PowerShell session. Hope this helps!