Point Deep

Mundeep's Tech Blog

Posts Tagged ‘Active Directory’

Powershell Script to Import Sharepoint Organization Profiles from Active Directory

Posted by mundeep on November 8, 2010

Here is one of my first Powershell scripts (so improvement suggestions welcome 🙂

The requirement was to script the creation of SharePoint Organization Profiles from Active Directory Organizational Units, including building the hierarchy and setting the Profile Subtype appropriately. Creation of the Organizational Profiles was based on the C# code in the How to: Create User Profiles and Organization Profiles MSDN article.

Before running this note that i had a predefined list of profile subtypes that corresponded to the level of the organizational unit in the hierarchy. The top level was Root, next level was Group, then Division, Branch & finally Section. The following is an example of the organizational structure in terms of Profile Subtypes.

  • Department (Root Level)
    • Group #1
      • Division #1
        • Branch #1
          • Section #1
      • Division #2
        • Branch #2
          • Section #2
          • Section #3
          • Section #4
        • Branch #3
          • Section #5
          • Section #6
      • Division #4
        • Branch #7
    • Group #2
      • Division #5
        • Branch #8
          • Section #9
      • Division #6
        • Branch #9
          • Section #10
          • Section #11
          • Section #12
      • Division #6
        • Branch #9
#Create All Organisation Profiles from AD OU's
#Load Sharepoint Snapin
Add-PSSnapin Microsoft.SharePoint.PowerShell
#Declare Some Globals for Profile Management
$context = Get-SPServiceContext -Site http://{sharepointwebappurl}/
$psm = [Microsoft.Office.Server.UserProfiles.ProfileSubtypeManager]::Get($context);
$opm = New-Object Microsoft.Office.Server.UserProfiles.OrganizationProfileManager($context)
$rootOrg = $opm.RootOrganization

#Find All Children OU's Based on Parent OU's Distinguished Name (DN)
function Find-Child-OUs
{
Param ([string]$sParentDN)
	$ldapPath = "LDAP://" + $sParentDN
	$query = new-object system.directoryservices.directorysearcher([ADSI]$ldapPath)
	#Only Search for OUs
	$query.filter = "(objectClass=organizationalUnit)"
	#Only Search One Level Deep (ie. Children)
	$query.SearchScope = "OneLevel"
	$results = $query.findAll()
	Write-Host $sParentDN " has " $results.Count " children"
	return $results
}

#Create an Organization Profile under parentOrg for provided OU
function Create-Organization {
Param ($ou, $parentOrg, $levelTitle)
	Write-Host "Creating:" $ou.description "under" $parentOrg.DisplayName "of type" $levelTitle
	$subType = $psm.GetProfileSubtype($levelTitle);
	$orgProfile = $opm.CreateOrganizationProfile($subType, $parentOrg)
	$orgProfile.DisplayName = $ou.description
	$orgProfile.Commit()
	return $orgProfile
}

#Determine Subtype Based on Level
function Get-Level-ProfileSubtype {
Param ($level)
	$subtypeTitle = $level
	switch ($level) {
		0 { $subtypeTitle = "Root"; break }
		1 { $subtypeTitle = "Group"; break }
		2 { $subtypeTitle = "Division"; break }
		3 { $subtypeTitle = "Branch"; break }
		4 { $subtypeTitle = "Section"; break }
		default { $subtypeTitle = "Other" }
	}
	return $subtypeTitle
}

#Create Organization Profiles for All OU's underneath the provided OU and Organization Profile
function Create-Child-Orgnizations
{
Param ([string]$currentOuDn, $parentOrg, $level)
	#Create the Organization
	Write-Host "Searching for Children for: " $currentOuDn
	$children = Find-Child-OUs $currentOuDn
	if ($children -ne $null) {
		Write-Host -ForegroundColor red $children.Count "OU's found under:" $currentOuDn
		Foreach($childOu in $children)
		{
			$ou = $childOu.GetDirectoryEntry()
			$ouDn = $ou.distinguishedname
			$levelTitle = Get-Level-ProfileSubtype($level)

			#Create the Child Organization
			$newOrg = Create-Organization $ou $parentOrg $levelTitle
			Write-Host -ForegroundColor green "OU Created: " $newOrg.DisplayName " = " $newOrg.ProfileSubtype.Name
			$nextLevel = $level + 1
			Create-Child-Orgnizations $ouDn $newOrg $nextLevel
		}
	}
}

#Create All Organization Profiles Starting from Provided OU DN
function Create-All-Organizations {
Param ([string]$rootOuDn)
	Create-Child-Orgnizations $rootOuDn $rootOrg 1
}

Once you have loaded all the globals and declared all the functions above the following two lines (can be done in one) will begin the profile creation.

#Run Creation From Root Orgnization Unit, Make sure the following matches the LDAP query to the Root OU in your AD structure.
$rootOu = "OU=Department,DC=depttest,DC=gov,DC=au"
Create-All-Organizations $rootOu

To help with testing & re-running code i also created a couple of functions to (a) List all Organizational Profiles under a parent and (b) Delete all Organization Profiles under a parent.

#Retrieve existing Org Profiles
function List-OrgProfiles {
Param($parentOrg)
	if ($parentOrg.HasChildren) {
		foreach ($childOrg in $parentOrg.GetChildren()) {
			Write-Host $parentOrg.DisplayName "-" $childOrg.DisplayName
			List-OrgProfiles $childOrg
		}
	}
}

#Delete existing Org Profiles
function Delete-OrgProfiles {
Param($parentOrg)
	# If Parent Has Children Delete them first
	if ($parentOrg.HasChildren) {
		foreach ($childOrg in $parentOrg.GetChildren()) {
			#Write-Host $childOrg.DisplayName " - " $parentOrg.DisplayName
			Delete-OrgProfiles $childOrg
		}
		#Once children are deleted remove the current org
		if ($parentOrg.RecordId -ne $opm.RootOrganization.RecordId) {
			$opm.RemoveOrganizationProfile($parentOrg.RecordId)
			Write-Host "Removing(" $parentOrg.DisplayName ")"
		}
		else {
			Write-Host "KEEP (" $parentOrg.DisplayName ")"
		}
	}
	else {
		#If not children then delete the current org
		if ($parentOrg.RecordId -ne $opm.RootOrganization.RecordId) {
			$opm.RemoveOrganizationProfile($parentOrg.RecordId)
			Write-Host "RemovingChildless(" $parentOrg.DisplayName ")"
		}
		else {
			Write-Host "Childless KEEP(" $parentOrg.DisplayName ")"
		}
	}
}
Advertisements

Posted in Powershell, Sharepoint | Tagged: , , , , | Leave a Comment »

What accounts does the people picker show?

Posted by mundeep on August 20, 2008

My colleague Ishai Sagi recently did some research into what accounts the people picker shows and determined the LDAP query that was being used to display accounts if you are using Windows authentication. I did some further research into this and i have noticed that aswell as your authentication provider source (eg. LDAP accounts for sites using Windows Authentication/Active Directory) the picker also shows accounts from the User Information List.

This is important to note as it means that accounts that may have been deleted or disabled in your authentication provider still come up to be selected by users that are entering information into a people field.

For further details on the User Information List see this article on Andrew Connell’s blog which appears to be for Sharepoint 2003 however seems to still mostly apply for MOSS. Also Sahil Malik has done some research into User Profile Information and how it flows.

Posted in Sharepoint | Tagged: , , , , | Leave a Comment »

Clearing Active Directory Values in C#

Posted by mundeep on August 5, 2008

To clear values in Active Directory they must be set to NULL and not “” or empty.
This can easily be done by using the Clear() method on the property value collection for the active directory field you wish to update.

using System.DirectoryServices;

public void ClearAdField(string fieldName, DirectoryEntry adEntry) {
  PropertyValueCollection adValue = adEntry.Properties[fieldName];
  adValue.Clear();
  adEntry.CommitChanges();
}

Posted in .NET | Tagged: , | 1 Comment »

A referral was returned from the server

Posted by mundeep on July 17, 2008

Running some code that updates active directory i ran into the following error message when trying to search for a user “A referral was returned from the server“. The problem was that the LDAP query i had used the wrong DC, and not the one that the user was in.

eg. my LDAP connection was: LDAP://devdcserver01.domain.int/DC=development,DC=domain,DC=int

when it should have been: LDAP://devdcserver01.domain.int/DC=dev,DC=domain,DC=int

This was because while the ‘friendly’ name of the domain you use when logging in was “DEVELOPMENT” however the fully qualified name was dev.domain.int

Posted in .NET | Tagged: , | Leave a Comment »