RSS

Monthly Archives: March 2012

How do I add Custom User Profile Properties with PowerShell

If you have used the Central Administration to add the User Profile Properties you are aware that it can be frustrating with the wait time on adding a single property. That led me to a research on how can we add User Profile Properties through PowerShell. That landed me to this blog – http://gallery.technet.microsoft.com/scriptcenter/SP2010-PowerShell-to-0fda04f7

It worked for me for single property but most of our clients do have multiple properties and that does come from separate connections including External Content Types. So, I did modify the above script and created a csv file of all the available properties that I needed to track. The CSV file has the following properties –

  1. PropertyName – This field is used for the Internal Name of the User Profile.
  2. DisplayName – This field is used for the Display Name property of the User Profile Property.
  3. Privacy – The allowed values are – Public, Contacts, Organization, Manager, Private and NotSet
  4. Privacy Policy – The allowed values are – Mandatory, OptIn, OptOut and Disabled
  5. Type – The data type of the property.
  6. Length – In case of string, enter this value or enter 0
  7. ConnectionName – The Synchronization connection name.
  8. AttributeName – The attribute from the synchronization that you would like to map to.
  9. IsMultivalued – Whether this property will hold multiple values.

My CSV file example looks as –

PropertyName,DisplayName,Privacy,PrivacyPolicy,Type,Length,ConnectionName,AttributeName,IsMultivalued
testskills,Test Skills,Public,Disabled,string,200,EmployeeSkills,Skill,true
testskills1,Test Skills1,Public,Disabled,string,200,EmployeeSkills,Skill,true

EmployeeSkills is the BCS connection that pulls in skills from our database.

The PowerShell script mentioned in the above blog was not working for me. So, I made a few changes. This script accepts two parameters –

Parameter 1 – The csv file path and name

Parameter 2 – The Site URL.

The main thing I added was the IsMultivalued property and also the check to see if the type is string then assign the length. The entire selection is within a foreach loop that goes through each line to pull the property information.

param($Parm1, $Parm2)
#Load SharePoint User Profile assemblies
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.Office.Server”)
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.Office.Server.UserProfiles”)
$userProps = Import-Csv $Parm1
 

 
#Get UserProfileManager
$mySiteUrl = $Parm2
$site = Get-SPSite $mySiteUrl
$context = Get-SPServiceContext $site
$upConfigManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($context)
$profilePropertyManager = $upConfigManager.ProfilePropertyManager
$coreprofilePropertyManager = $profilePropertyManager.GetCoreProperties()
$userProfileTypeProperties = $profilePropertyManager.GetProfileTypeProperties([Microsoft.Office.Server.UserProfiles.ProfileType]::User)
$userProfileSubTypeManager = [Microsoft.Office.Server.UserProfiles.ProfileSubTypeManager]::Get($context)
$userProfile = $userProfileSubTypeManager.GetProfileSubtype([Microsoft.Office.Server.UserProfiles.ProfileSubtypeManager]::GetDefaultProfileName([Microsoft.Office.Server.UserProfiles.ProfileType]::User))
$userProfileProperties = $userProfile.Properties 

Foreach ($userProp in $userProps)
{
#Set Custom Property values
$PropertyName = $userProp.PropertyName
$PropertyDisplayName = $userProp.DisplayName
$Privacy= $userProp.Privacy
$PrivacyPolicy = $userProp.PrivacyPolicy
$coreProperty = $coreprofilePropertyManager.Create($false)
$coreProperty.Name = $PropertyName
$coreProperty.DisplayName = $PropertyDisplayName
$coreProperty.Type = $userProp.Type

#Check if the Type is string then assign the length.
if ($userProp.Type -eq ‘string’)
{
$coreProperty.Length = $userProp.Length
}

if ($userProp.IsMultivalued -eq ‘true’)
{
$coreProperty.IsMultivalued = $true
}
$foundProperty = $coreprofilePropertyManager.GetPropertyByName($userProp.PropertyName)

#if the property is found then we delete that property.
if ($foundProperty -ne $null)
{

#Uncomment the code to delete the property.
#$coreprofilePropertyManager.RemovePropertyByName($userProp.PropertyName)
}
$coreprofilePropertyManager.Add($coreProperty)
$profileTypeProperty = $userProfileTypeProperties.Create($coreProperty)
#Show on the Edit Details page
$profileTypeProperty.IsVisibleOnEditor = $true
 
#Show in the profile properties section of the user’s profile page
$profileTypeProperty.IsVisibleOnViewer = $true
 
#Show updates to the property in newsfeed
$profileTypeProperty.IsEventLog = $true
 
$userProfileTypeProperties.Add($profileTypeProperty)
$profileSubTypeProperty = $userProfileProperties.Create($profileTypeProperty)
$profileSubTypeProperty.DefaultPrivacy =[Microsoft.Office.Server.UserProfiles.Privacy]::$Privacy
$profileSubTypeProperty.PrivacyPolicy = [Microsoft.Office.Server.UserProfiles.PrivacyPolicy]::$PrivacyPolicy
$userProfileProperties.Add($profileSubTypeProperty)
 
#Add New Mapping for synchronization user profile data
#SharePoint Synchronization connection
$connectionName =$userProp.ConnectionName
 
#Attribute name in Connection Source

$attributeName =$userProp.AttributeName
 
$synchConnection = $upConfigManager.ConnectionManager[$connectionName]
$synchConnection.PropertyMapping.AddNewMapping([Microsoft.Office.Server.UserProfiles.ProfileType]::User,$PropertyName,$attributeName)

}

 

You can use this code at your own risk 🙂

Good luck with PowerShell Scripting.

 
1 Comment

Posted by on March 13, 2012 in Uncategorized

 

How do I point SharePoint User Profile photos to a network share or a web site that contains employee photos?

I have been asked this often – “Our company takes employee photos and we store it on a network folder. We would like to use the company photos instead of users uploading their own photos?”

Background:

The way SharePoint user profiles image work is –

  • All the images are stored on http://<MySiteURL>/User%20Photos/Forms
  • For each user profile there are three sizes for the images. When you upload an image SharePoint converts those to three different sizes and stores it in the above image library.

After googling I found lot of code that would upload the images to the above mentioned library but there was lot of code that would also convert the images into the different sizes and store it. Initially I was inclined towards trying the above route but soon I realized that the client for whom I was working was storing the images with employeeID.jpg format. Most of the code I found online was talking about network name. So, I would have to first compare the employee ID get the image convert it to SharePoint understandable size and then upload it to the library. I had to get this done in 2 hours. So, I started looking for how can I just point the pictureURL property for the User Profile to point to the network drive and just be done with it.

So, there were two options –

  1. Write C# code to populate the pictureURL property. But this would mean I would have to create a setup application and then install it on the server. Didn’t like the option…
  2. Somehow work with PowerShell Script. Did more googling and found the various pieces of the puzzle and brought it together. Following is the solution whch works great for our client.

Solution:

The solution assumes you have already created the User Profile connection with AD. If you are using the EmployeeID as your identifier for your user profile images then make sure you create User Profile property for employeeID and map it to the AD employeeID field. You also need to setup the MySites web application and the url stuff.

Once your user profile is setup and the import is performed. You have to make sure that you have given full control of User Profile Service Application to the user that would be running the PowerShell Script. In order to do that follow these steps –

  • Go to Central Administration.
  • Click on Application Management.
  • Click on Manage Service Applications.
  • Select the User PRofile Service Application. Do not click on the Service Application link.
  • Click on Permissions on the Service Applications Ribbon.
  • If the user you are using to run the PowerShell Script is not in this list then add it and give it full control.

Once the above steps are done now you can use the following PowerShell Script to point the PictureURL to the appropriate location –

#Get the My Site URL Replace the <MySites URL with your url
$siteUrl = “”

#Get the Site Context
$site = Get-SPSite $siteUrl
$servcontext = Get-SPServiceContext $site

#Initiate the Profile Manager and get the user profiles
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($servcontext)
$profiles = $profileManager.GetEnumerator()

#The property names for picture url and employeeid.
$pictureURLAttribute = “PictureURL”
$employeeIDAttribute = “EmployeeId”

# Loop through all user profiles.
foreach ($uProfile in $profiles)
{
# Make sure there is some value in the employee ID property
if ($uProfile[$employeeIDAttribute] -ne ”)
{
 #Get the EmployeeID for the employee.
 $EmployeeID = $uProfile[$employeeIDAttribute].toString()
 #Format the Picture url. Since this example is for network folders the format starts with \\ Replace the
 $netPictureURL = “\\<network folder>\$EmployeeID.jpg”
 
 #Change the Picture URL information and then commit the record.
 $uProfile[$pictureURLAttribute].Value = $netPictureURL
 $uProfile.Commit()

 }

}

Run the above PowerShell script and all your user profiles will point to the network drive for employee photo.

But if you try to search the results you will still not see the photos on the Search results. Even after running the incremental crawl does not help on the Search Results. Here is the reason why it does not work. If you look at the Search results XSLT code, it actually blocks files that start with \\ or file: or //. You need to modify the XSLT to allow the image files that start with \\ or file:. In order to do that follow these steps –

  • Go to peopleresults.aspx page and edit it.
  • Edit the People core search results web part.
  • Expand Display properties.
  • Uncheck the Use Location Visualization checkbox.
  • Click on XSL Editor button.
  • Search for GetPicUrl. The code should be as follows –

<xsl:template name=”GetPicUrl”>
  <xsl:param name=”PicUrl”/>
  <xsl:param name=”PlaceHolderUrl”/> 
  <xsl:choose>
    <xsl:when test=”string-length($PicUrl) < 1 or starts-with($PicUrl, ‘file:’) or starts-with($PicUrl, ‘\\’) or starts-with($PicUrl, ‘//’)”>
      <xsl:value-of select=”$PlaceHolderUrl”/>
    xsl:when>
    <xsl:otherwise>
      <xsl:value-of select=”$PicUrl”/>
    xsl:otherwise>
  xsl:choose>
xsl:template>

  • Note that the PicUrl is being checked for blank or if it starts with file: or \\ or //. If any of these conditions are true then it displays the default picture if it is false then it actually displays the pictureURL. . Remove all the starts-with code and now the images are visible in the search results page. Your code should now look like –

<xsl:template name=”GetPicUrl”>
  <xsl:param name=”PicUrl”/>
  <xsl:param name=”PlaceHolderUrl”/> 
  <xsl:choose>
    <xsl:when test=”string-length($PicUrl) < 1″>
      <xsl:value-of select=”$PlaceHolderUrl”/>
    xsl:when>
    <xsl:otherwise>
      <xsl:value-of select=”$PicUrl”/>
    xsl:otherwise>
  xsl:choose>
xsl:template>

  • Just in case anyone is wondering how does this template get call. Search for pictureURL. You will get the code which calls this template and passes the pictureURL managed property as parameter.

The above step should assist you with your company policies of using the company photos for user profiles and not the employee uploaded photos.

Happy SharePoint Searching. Use the above code at your own risk 🙂

 

 
1 Comment

Posted by on March 12, 2012 in Uncategorized

 

What format are the SharePoint files with extension .stp, .xsn and .wsp?

The answer is simple it is CAB format.

Recently, I was faced with a situation where I had a old SharePoint list template from WSS 3 and that would not import in SharePoint 2010. The solution was simple. Here is what I did –

  • Renamed the .stp file to .cab.
  • Extracted the manifest.xml
  • Changed the element ProductVersion from 3 to 4.
  • Repackaged the file to CAB file. You can create .ddf file and then use the makecab command. Check this link on how to package a web part. Same concept can be used for packaging the .stp file.
  • Rename the .cab to .stp file and import it. AND now you can create a list based on this template.

Similarly, if you are on a computer without InfoPath installed and would like to look at the schema used. Just rename the file to .cab and extract the files. You will notice that .xsn file is made up of multiple files. You can open the template.xml file to find out how your xml could be stored. It also has all the xsd and image files that are included in your InfoPath form.

Good luck with your development on SharePoint.

 
1 Comment

Posted by on March 2, 2012 in Uncategorized