Wednesday, November 20, 2013

Scheduled Task to Add Colleagues in SharePoint

Here is the use case in SharePoint 2010/2013: HR wants all employees to add some key people in your organization as colleagues, so that everyone inside the company would be able to see their posts and feeds. A simple powershell script can do the job:

## Add SharePoint Snap-in
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

## Get profiles
$site = Get-SPSite("https://my_company_portal")
$context = Get-SPServiceContext $site
$profilemanager = New-object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
 
## People who will be the common colleagues for all employees
$vipNames = "domain\user1", "domain\user2", "domain\user3"
$vipMembers = @()
foreach($vipName in $vipNames) {
    try {      
        $vipUser = $profilemanager.GetUserProfile($ecName)
        $vipMembers += $vipUser
    } catch {
        write-output $_.Exception.Message
   }   
}
 
## Colleague setting
$group = "General"
$groupType = [microsoft.office.server.userprofiles.colleaguegrouptype]::General
$privacy = [microsoft.office.server.userprofiles.privacy]::Public
$isInWorkGroup = $false
 
## Go through all users and add colleagues
$profiles = $profilemanager.GetEnumerator()
foreach($user in $profiles) {
    foreach($vipMember in $vipMembers) {
        if (($user.ID -ne $vipMember.ID) -and !($user.Colleagues.IsColleague($vipMember[0].ID))) {
            try {      
                $user.Colleagues.CreateWithoutEmailNotification($vipMember, $groupType, $group, $isInWorkGroup, $privacy)
            } catch {
                write-output $_.Exception.Message
            }
        }
    }
}
How about the new hires? We can setup a scheduled task to run the powershell script so the profile update will be applied weekly or daily. Open Task Scheduler from Administrative Tools or Control Panel, create a Task with following settings:
  • General tab:
    • Name: "Add colleagues"
    • Make sure the account running the task having sufficient permission to update the SharePoint Profile database
    • Check (enable) "Run whether user is logged on or not"
    • Check (enable) "Run as highest privileges"
  • Triggers tab:
    • Create a new trigger: Weekly or daily at midnight
  • Actions tab:
    • Select "Start a program" type
    • Program/script: powershell
    • Add arguments (optional): -Command "C:\SharePointScheduledTasks\addColleagues.ps1"

In case you don't like powershell script, following code is the equivalent c# version doing the exact same task:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
 
class Program
{
    static void Main(string[] args)
    {
        UpdateUsersProfile("https://my_company_portal");
    }
 
    private static void UpdateUsersProfile(string siteUrl)
    {
        using (SPSite spSite = new SPSite(siteUrl))
        {
            SPServiceContext context = SPServiceContext.GetContext(spSite);
            UserProfileManager profileManager = new UserProfileManager(context);
 
            List<UserProfile> vipMeMembers = GetVipMembers(profileManager);
 
            foreach (UserProfile profile in profileManager)
            {
                AddColleagues(profile, vipMeMembers);
            }
        }
    }
 
    private static List<UserProfile> GetVipMembers(UserProfileManager profileManager)
    {
        List<string> vipUserNames = new List<string>() { "domain\\user1", "domain\\user2", "domain\\user3" };
        List<UserProfile> vipMembers = new List<UserProfile>();
 
        foreach (string name in vipUserNames)
        {
            try
            {
                UserProfile vipMember = profileManager.GetUserProfile(name);
                vipMembers.Add(vipMember);
            }
            catch (Exception ex)
            {
                // User doesn't exit
            }
        }
        return vipMembers;
    }
 
    private static void AddColleagues(UserProfile user, List<UserProfile> colleagues)
    {
        foreach (UserProfile colleague in colleagues)
        {
            if (user.ID != colleague.ID && !user.Colleagues.IsColleague(colleague.ID))
            {
                user.Colleagues.CreateWithoutEmailNotification(colleague, 
                    ColleagueGroupType.General, "General", false, Privacy.Public);
            }
        }
    }
}