The information in this article is based on BETA 2 of SharePoint 2010 – there may be differences with the RTM release.

Update 12/18/2009: I’ve updated the post to reflect BETA 2 changes and have considerably simplified the script removing all the dependencies on helper functions so that the core pieces required to build a basic farm are focused on rather than the complex elements to support tracing and error handling as I previously had it.

If you’ve ever done a scripted install of SharePoint 2007 then you are familiar with how to script the initial farm creation using <strong>psconfig.exe</strong>. Unfortunately psconfig is still with us in SharePoint 2010 but we do have some PowerShell cmdlets which replace all the psconfig commands.

Before we look at how to use PowerShell lets refresh our memories by looking at an install script for SharePoint 2007. I usually have two scripts, one for the first server and a second script for additional servers – here’s the first script (I’ve omitted the variable declarations):

 1ECHO %DATE% %TIME%:  Building configuration database
 2psconfig -cmd configdb -create -server %SERVER_DB% -database %DB_CONFIG_NAME% -user %ACCT_SPFARM% -password %ACCT_SPFARM_PWD% -admincontentdatabase %DB_CENTRALADMINCONTENT_NAME% 
 3if not errorlevel 0 goto errhnd
 4 
 5ECHO %DATE% %TIME%: Installing help content
 6psconfig -cmd helpcollections -installall 
 7if not errorlevel 0 goto errhnd
 8 
 9ECHO %DATE% %TIME%: Securing resources
10psconfig -cmd secureresources 
11if not errorlevel 0 goto errhnd
12 
13ECHO %DATE% %TIME%: Installing services
14psconfig -cmd services -install 
15if not errorlevel 0 goto errhnd
16 
17ECHO %DATE% %TIME%: Installing features
18psconfig -cmd installfeatures 
19if not errorlevel 0 goto errhnd
20 
21ECHO %DATE% %TIME%: Creating central admin site
22psconfig -cmd adminvs -provision -port %CENTRALADMIN_PORT% -windowsauthprovider enablekerberos 
23if not errorlevel 0 goto errhnd
24 
25ECHO %DATE% %TIME%: Adding application content to central admin site
26psconfig -cmd applicationcontent -install
27if not errorlevel 0 goto errhnd
28 
29goto end
30 
31:errhnd
32 
33echo An error occured - terminating script.
34 
35:end

And here’s the second script (variable declarations omitted):

 1ECHO %DATE% %TIME%: Connecting to farm
 2psconfig -cmd configdb -connect -server %SERVER_DB% -database %DB_CONFIG_NAME% -user %ACCT_SPFARM% -password %ACCT_SPFARM_PWD%
 3if not errorlevel 0 goto errhnd
 4 
 5ECHO %DATE% %TIME%: Installing services
 6psconfig -cmd services install
 7if not errorlevel 0 goto errhnd
 8 
 9ECHO %DATE% %TIME%: Installing features
10psconfig -cmd installfeatures
11if not errorlevel 0 goto errhnd
12 
13ECHO %DATE% %TIME%: Setting security on registry and file system
14psconfig -cmd secureresources
15if not errorlevel 0 goto errhnd
16 
17goto end
18 
19:errhnd
20 
21echo An error occured - terminating script.
22 
23:end

Obviously the two scripts are very similar with the main difference being the parameters passed to the configdb command and with fewer commands being called. So how would we do this using SharePoint 2010’s PowerShell cmdlets? First lets list each psconfig command and what the PowerShell equivalent is:

PSConfig CommandPowerShell Cmdlet
configdb -createNew-SPConfigurationDatabase
configdb -connectConnect-SPConfigurationDatabase
helpcollections -installallInstall-SPHelpCollection
secureresourcesInitialize-SPResourceSecurity
services -installInstall-SPService
installfeaturesInstall-SPFeature (provide the -AllExistingFeatures parameter)
adminvs -provisionNew-SPCentralAdministration
applicationcontent -installInstall-SPApplicationContent

Now that we know what PowerShell cmdlets to use lets rework our install script. Instead of using a batch file for variables I’m going to use an XML file which can be read in and parsed as needed. I’m also going to make it so that you can run the same script from any server and just specify a switch parameter indicating whether or not you are connecting to an existing farm or not.

Let’s first take a look at the XML that we’ll use to manage our settings – we’ll store this in a file called FarmConfigurations.xml:

 1<Farm FarmAccount="sp2010\spfarm" 
 2      ConfigDB="SharePoint_ConfigDB" 
 3      AdminContentDB="SharePoint_Content_Admin"
 4      DatabaseServer="spsql1" 
 5      Passphrase="Pa$$w0rd">
 6    <CentralAdmin Port="1234" AuthProvider="NTLM">
 7        <Servers>
 8            <Server Name="spsvr1" />
 9        </Servers>
10    </CentralAdmin>
11</Farm>

In this XML I’m storing the core farm settings in the <Farm /> element which includes attributes for the farm account to use as well as the database server and names for the configuration and central admin content database. I then have a <CentralAdmin /> element which contains the servers that the Central Admin site should be installed on along with the port and authentication provider to use.

So now that we have our configuration settings all we need now is the core script to actually create our farm. I named this script BuildFarm.ps1 but you can name it whatever you want:

 1function Install-SharePointFarm([bool]$connectToExisting, 
 2    [string]$settingsFile = "FarmConfigurations.xml") {
 3    
 4    $config = Get-Content $settingsFile
 5
 6    $farmAcct = Get-Credential $config.Farm.FarmAccount
 7
 8    $configDb = $config.Farm.ConfigDB
 9    $adminContentDb = $config.Farm.adminContentDb
10    $server = $config.Farm.DatabaseServer
11    if ($config.Farm.Passphrase.Length -gt 0) {
12        $passphrase = (ConvertTo-SecureString $config.Farm.Passphrase `
13            -AsPlainText -force)
14    } else {
15        Write-Warning "Using the Farm Admin's password for a passphrase"
16        $passphrase = $farmAcct.Password
17    }
18    
19    #Only build the farm if we don't currently have a farm created
20    if (([Microsoft.SharePoint.Administration.SPFarm]::Local) -eq $null) {
21        if ($connectToExisting) {
22            #Connecting to farm
23            Connect-SPConfigurationDatabase -DatabaseName $configDb `
24                -DatabaseServer $server -Passphrase $passphrase
25        } else {
26            #Creating new farm
27            New-SPConfigurationDatabase -DatabaseName $configDb `
28                -DatabaseServer $server `
29                -AdministrationContentDatabaseName $adminContentDb `
30                -Passphrase $passphrase -FarmCredentials $farmAcct
31        }
32        #Verifying farm creation
33        $spfarm = Get-SPFarm -ErrorAction SilentlyContinue -ErrorVariable err
34        if ($spfarm -eq $null -or $err) {
35            throw "Unable to verify farm creation."
36        }
37        
38        #ACLing SharePoint Resources
39        Initialize-SPResourceSecurity
40
41        #Installing Services
42        Install-SPService
43        
44        #Installing Features
45        Install-SPFeature -AllExistingFeatures
46    } else {
47        Write-Warning "Farm already exists. Skipping creation."
48    }
49    
50    $installSCA = (($config.Farm.CentralAdmin.Servers.Server | `
51        where {$_.Name -eq $env:computername}) -ne $null)
52    $url = "http://$($env:computername):$($config.Farm.CentralAdmin.Port)"
53    $sca=[Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($url)
54    if ($installSCA -and $sca -eq $null) {
55        #Provisioning Central Administration
56        New-SPCentralAdministration -Port $config.Farm.CentralAdmin.Port `
57            -WindowsAuthProvider $config.Farm.CentralAdmin.AuthProvider
58       
59        #Installing Help
60        Install-SPHelpCollection -All
61
62        #Installing Application Content
63        Install-SPApplicationContent
64    }
65} 

Notice that the script takes a parameter which allows you to specify whether you are connecting to an existing farm. We can call the script using the following syntax (replace $false with $true if connecting to an existing farm):

1PS C:\> . .\buildfarm.ps1
2PS C:\> Install-SharePointFarm $false "FarmConfigurations.xml"

In a series of upcoming post I’ll be building on what I created here by demonstrating how to create web applications and how to start each of the services that are included, including the extremely complex search service (gone are the days of a single line setup for search – we now have a dozen or so cmdlets that have to be run to get search started).