This topic is going to discuss creating a new user profile service application in SharePoint Server 2010 using PowerShell.  In the process, I hope to provide some guidance on how to avoid some common pitfalls with setting up the user profile service application, some specific to creating user profile service applications with PowerShell.  The sample script provided does focus on the SharePoint PowerShell cmdlets, and additional work is required at the domain level in order for this to work.  The entire process could be performed in one Active Directory script, but that would require running the script as a domain administrator, and running the script as the SharePoint farm administrator is already bad enough.

Background

When I first started working with SharePoint Server 2010, I had the same issues as most of my customers and found it almost impossible to set up the user profile service application without running into at least one or two problems.  Either the user profile synchronization service would get stuck in a starting state, or I wouldn't be able to successfully read user profiles from Active Directory, or push user profile information updated in SharePoint back into Active Directory.

Approach

Anybody who has attempted to create a user profile service application in SharePoint Server 2010 will tell you that it looks very simple in principal.  In the end, you want to just create a service application.  We have a PowerShell cmdlet for that (the same as we do for all other service applications).  Various services on at least one server need to be started for certain service applications to function.  The user profile service application requires the "User Profile Service" and the "User Profile Synchronization Service" to be running in order for the service application to provide the intended functionality.

So, effectively, the approach is to Configure the required service accounts to have the required level permissions and delegated rights.  You then need to ensure the required services are started on the target servers before using the New-SPProfileServiceApplication PowerShell cmdlet to create a user Profile Service Application.  Finally, associate an instance of the user profile synchronization service to the user profile service application and start the service instance.

Pre-Requisites

Some of the challenges we encounter when setting up the user profile service application is the fact that we typically overlook many of the pre-requisites.  Documentation has gotten a considerably better since the initial release of the product, and at this point, there's no reason for any of us to continue struggling with User Profile Service Application deployment.

First thing is first. There are some domain level pre-requisites that you must meet. I won't enumerate them – they should take 15 minutes at most to implement and this is thoroughly documented here:
Grant Active Directory Domain Services permissions for profile synchronization (SharePoint Server 2010)

Using the script I've provided, you will also need to be logged on to the server using the SharePoint farm account, and this account will also have to be a local administrator. The requirement for the farm account (synchronization account) to be a local administrator on the server until the synchronization service is started is non-negotiable. The need to log on to the server using the farm account is something that can be worked around using information from the following blog post:
Avoiding the Default Schema issue when creating the User Profile Service Application using Windows PowerShell

Once you've taken care of these pre-requisites, you should be able to run the sample script provided.

Solution

As I mentioned in the approach, this really isn't that difficult of a process… as long as you've taken care of the pre-requisites. It comes down to creating an application pool for the User Profile Service Application proxy, creating the User Profile Service Application, and creating the User Profile Service Application proxy. The relevant portion of the script is as follows:

$UserProfileServiceApplicationAppPool = New-SPServiceApplicationPool -Name $UserProfileServiceName -Account $UserProfileServiceAccount
$UPSI = get-spserviceinstance | where {$_.server -like "*" + $ProfileSyncServer -and $_.Typename -eq "User Profile Service"} | Start-SPServiceInstance
$UserProfileSyncServiceInstance = get-spserviceinstance | where {$_.server -like "*" + $ProfileSyncServer -and $_.Typename -eq "User Profile Synchronization Service"}
$UserProfileSA = New-SPProfileServiceApplication -Name $UserProfileServiceName -ApplicationPool $UserProfileServiceApplicationAppPool -ProfileDBName $UserProfileDB -ProfileSyncDBName $UserProfileSyncDB -SocialDBName $UserProfileSocialDB
$SPUserprofileMachine = get-spserver $ProfileSyncServer
$UserProfileSA.SetSynchronizationMachine($ProfileSyncServer, $UserProfileSyncServiceInstance.id, $UserProfileSyncAccount.username, $FarmAccountPassword)
New-SPProfileServiceApplicationProxy -Name ($UserProfileServiceName + " Proxy") -ServiceApplication $UserProfileSA
Start-SPServiceInstance $UserProfileSyncServiceInstance

Attempting to manage a user profile service application directly after provisioning the service will result in a very unhelpful error message being displayed. This can typically be remediated by performing an IISReset. In the sample script provided, I do wait for the User Profile Synchronization Service to successfully start and then perform an IISReset on the server hosting the service. This should bypass that problem.

You can download the sample script from the following location: Download CreateUserProfileServiceApplication.ps1 (zipped)

Usage

Ensure you meet all pre-requisites before running the script. Ensure your farm account is a local administrator on your SharePoint server where the user profile synchronization service will be started. Log on to your SharePoint server using the SPFarm account. Modify the variables at the top of the script with values to match your environment, and execute the script.

Feedback

As always, if you have any questions or feedback, let me know. If you have any ideas to optimize the script, I'd like to hear that too. Thanks for reading!

 You can also follow me on Twitter: 

 RCormier_MSFT