As I described earlier, you can create synchronization connection with User Profiles for Active Directory via PowerShell. And what about the Business Connectivity Services? It’s also possible, of course!
As well as in the previous post, the core of our script is the UserProfileConfigManager class that contains the ConnectionManager property with several methods for adding new connections with user profiles.
The main difference that this time we'll use the AddBusinessCatalogConnection method which has eight parameters (it’s much more than almost any method in the .Net BCL).
public BusinessDataCatalogConnection AddBusinessDataCatalogConnection(
string displayName,
string systemName,
string entityName,
string entityNamespace,
string profilePropertyName,
string filterName,
string mappedPropertyAttributeName, List<DSMLAttribute> attributeList )
There are simple parameters, except the last: the list of instances of DSMLAttribute (non-documented) class. This class is a simple set of properties, as you can see in the picture below.
Note: DSML – an acronym that means the Directory Services Markup Language. You can find more information about that on Wikipedia.
Before we begin, I assume that we already have an entity in the BCS model that has at least one method “Read Item” (Specific Finder). Identifier of the entity is a field containing a user account name (it will be mapped to the profile property “Account Name”).
Now, we can code our script. Listing below:
Add-BCSConnection.ps1
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
function Get-First { return @($input)[ 0] }
function Get-Last { return @($input)[-1] }
function Convert-ToList($inputObject, [System.String]$Type)
{
begin
{
if($type -eq $null -or $type -eq '')
{
$type = [string]
}
$list = New-Object System.Collections.Generic.List[$type]
}
process { $list.Add($_) }
end { return ,$list }
}
function Get-SPServiceContext(
[Microsoft.SharePoint.Administration.SPServiceApplication]$profileApp)
{
if($profileApp -eq $null)
{
# Get first User Profile Service Application
$profileApp = Get-SPServiceApplication |
? { $_.TypeName -eq "User Profile Service Application" } |
Get-First
}
return [Microsoft.SharePoint.SPServiceContext]::GetContext(
$profileApp.ServiceApplicationProxyGroup,
[Microsoft.SharePoint.SPSiteSubscriptionIdentifier]::Default)
}
function Convert-ToDSMLSyntax([System.String]$typeName)
{
$DSMLSyntaxType = [Microsoft.Office.Server.UserProfiles.Synchronization.DSMLSyntax, Microsoft.Office.Server.UserProfiles.Synchronization, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c]
if($typeName -match "System.DateTime")
{
return $DSMLSyntaxType::Date
}
if($typeName -match "System.Int32")
{
return $DSMLSyntaxType::Integer
}
if($typeName -match "System.Byte")
{
return $DSMLSyntaxType::Binary
}
if($typeName -match "System.Boolean")
{
return $DSMLSyntaxType::Boolean
}
return $DSMLSyntaxType::String
}
# Global
$DSMLSyntaxType = [Microsoft.Office.Server.UserProfiles.Synchronization.DSMLSyntax, Microsoft.Office.Server.UserProfiles.Synchronization, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c]
$DSMLAttributeType = [Microsoft.Office.Server.UserProfiles.Synchronization.DSMLAttribute, Microsoft.Office.Server.UserProfiles.Synchronization, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c]
$connectionName = "BCS Connection"
$entityName = "ExternalUserInfo"
$entityNamespace = "ExternalUserInfoDatabase"
$profilePropertyName = "AccountName"
# Main()
$serviceContext = Get-SPServiceContext
# Prepare parameters
$entity = Get-SPBusinessDataCatalogMetadataObject -BdcObjectType Entity `
-ServiceContext $serviceContext `
-Name $entityName `
-Namespace $entityNamespace
$entityIdentifier = $entity.Identifiers | Get-First
$specificFinder = $entity.Methods |
% { $_.MethodInstances } |
? { $_.MethodInstanceType -eq "SpecificFinder" } |
Get-First
$attrList = $specificFinder.ReturnTypeDescriptor.ChildTypeDescriptors |
% {
$attribute = New-Object $DSMLAttributeType
$attribute.ID = $_.Name
$attribute.Name = $_.Name
$attribute.Indexible = $false
$attribute.SingleValued = $true
$attribute.Syntax = Convert-ToDSMLSyntax($_.TypeName)
$attribute
} | Convert-ToList -Type $DSMLAttributeType
# Important: Special property for BCS connection!
$attribute = New-Object $DSMLAttributeType
$attribute.ID = "SPS-DistinguishedName"
$attribute.Name = "SPS-DistinguishedName"
$attribute.Indexible = $true
$attribute.SingleValued = $true
$attribute.Syntax = Convert-ToDSMLSyntax("System.String")
$attrList.Add($attribute);
# Create BCS Connection
$configMgr = New-Object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($serviceContext)
$connectionMgr = $configMgr.ConnectionManager
if(!$connectionMgr.Contains($connectionName))
{
$connectionMgr.AddBusinessDataCatalogConnection(
<# displayName: #> $connectionName,
<# systemName: #> $entity.LobSystem.Name,
<# entityName: #> $entity.Name,
<# entityNamespace: #> $entity.Namespace,
<# profilePropertyName: #> $profilePropertyName,
<# filterName: #> $null,
<# mappedPropertyAttributeName: #> $entityIdentifier.Name,
<# attributeList: #> $attrList)
}
Note: If you try to execute code and get error:
Exception calling "AddBusinessDataCatalogConnection" with "8" argument(s): "Could not connect to http://[server-name]:[random-port]/ResourceManagementService/MEX. TCP error co
de 10061: No connection could be made because the target machine actively refused it [ip-address]:[random-port]. "
At C:\[some-path]\Add-BCSConnection.ps1:+ $connectionMgr.AddBusinessDataCatalogConnection <<<< (
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
You must start Forefront Identity Manager Service (via services.msc console) and try again.
That’s all.
And, of course, I hate it!