Friday 27 June 2014

Get User Profile Synchronization connections in PowersShell and Advanced SharePoint functions in PowerShell

Maybe you have noticed that in SharePoint 2013 and SharePoint 2010 SP1 we have two cmdlets about Profile Sync. connections Add-SPProfileSyncConnection and Remove-SPProfileSyncConnection.
But against the PowerShell logic we have no Get-SPProfileSyncConnection cmdlet to list the current connections. In this post I am going to show you a short PowerShell function that I wrote that does this and going to explain some of the good practices when you develop advanced PowerShell functions for SharePoint. You can see the function below, it is really short.

function Get-SPProfileSyncConnection
{
 [CmdletBinding(DefaultParameterSetName="PSet1")]

Param(
    [parameter(Mandatory=$true,
        ParameterSetName="PSet1",
        ValueFromPipeline=$true)]
    [Microsoft.SharePoint.PowerShell.SPServiceApplicationPipeBind]$UPA,
    [parameter(Mandatory=$true,
        ParameterSetName="PSet2",
        ValueFromPipeline=$false)]
    [System.String]$UPAName
)
PROCESS{
    switch ($PsCmdlet.ParameterSetName) 
    {
        "PSet1" { $UPApp = $UPA.Read(); break} 
        "PSet2" { $UPApp = Get-SPServiceApplication | Where {$_.Name -eq $UPAName}; break} 
    }
    $context = [Microsoft.SharePoint.SPServiceContext]::GetContext($UPApp.ServiceApplicationProxyGroup,[Microsoft.SharePoint.SPSiteSubscriptionIdentifier]::Default)
    $upcMan = New-Object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($context)
    
    Write-Output $upcMan.ConnectionManager
    
}
}

Because of the specifics in User Profile Service Application(UPA) the function must run under the Farm account identity.
Now lets have a look on what is going on. In all cases we need to have a User Profile Service Application from where we can get the sync. connection(s) or other service application with proxy in the same proxy group as our target UPA, so we can get the Service context , this should be defined by the user as parameter. At the parameter section of the function we have defined two parameters from two parameter sets, UPA from parameter set PSet1 and UPAName from parameter set PSet2. The script can get the desired User Profile Service Application from both parameters. If the user have supplied a value for parameter UPAName, the script will decide how to assign value to the UPApp that represent our User Profile Service Application object. If the UPAName is present that means that PSet2 is used. This logic is achieved with the PowerShell switch statement. If the PSet2 is used the script will assign value of Service Application where the Name property is equal to the UPAName supplied by the user.
The interesting part is when UPA parameter is used (PSet1). This parameter is set to receive value from pipeline. This is achieved by parameter argument ValueFromPipeline=$true , it means that this parameter will take the value of object from the pipeline if it is the same type as the parameter (bind byValue). The type of the parameter is not Microsoft.Office.Server.Administration.UserProfileApplication
for example, it is Microsoft.SharePoint.PowerShell.SPServiceApplicationPipeBind .
In the native SharePoint cmdlets parameter 'Identity' can be represented by multiple ways. For examaple if you want to get SPSite with the cmdlet Get-SPSite. You can supply URL, GUID or entire SPSite object. If you need to get all sites from a web application, you will use "Get-SPSite -WebApplication"  and for the WebApplication parameter you can supply URL,ID, entire SPWebApplication object or use pipeline, because the expected type is SPWebApplicationPipeBind. In order to prevent the need for multiple parameters and multiple parameter sets Microsoft presented the PipeBind objects. After you supply valid object and valid object is object that can be converted by the PipeBind (GUID,String,..etc) you are converting it to the original object by calling Read() method. You can have a look at the available PipeBind classes in this MSDN Library .
You may have issues with the above function in advanced scenario with multiple proxies/proxy groups or with partitioned (multi-tenant) environment(haven't tested it yet), maybe it is better to take the ServiceContext from SPSite. I think it is a good example for creating a SharePoint cmdlet and it is working well in my case .


No comments:

Post a Comment