Top Menu

Showing posts with label User Profile. Show all posts
Showing posts with label User Profile. Show all posts

Tuesday, June 24, 2014

SharePoint 2013 - Delete UserProfile Data with PowerShell

Description:
This PowerShell script will take two input files Users.csv (with all the user names under USERID column) and Properties.csv (with all the properties under TITLE column) and delete the values of UPA properties for the given users.

Script:
#PowerShell Script - Delete User Profile Properties Data in MySite 2013 UPA

Add-PSSnapin "Microsoft.SharePoint.PowerShell"

function WriteLog
{
    Param([string]$message, [string]$logFilePath)
    Add-Content -Path $logFilePath -Value $message
}


#################################################################################################

$logFile = "D:\PowerShellScripts\DeleteUserProfileDataInUPA\DeleteUserProfileDataInUPA.log"
$batchFile = "D:\PowerShellScripts\DeleteUserProfileDataInUPA\Users.csv"
$PropertiesFile = "D:\PowerShellScripts\DeleteUserProfileDataInUPA\Properties.csv"
$mysiteHostUrl = "http://company.MySite.com"


$mysite = Get-SPSite $mysiteHostUrl
$context = [Microsoft.Office.Server.ServerContext]::GetContext($mysite)
$upm =  New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

$currentProfile = 0

$Properties = Import-CSV $PropertiesFile

$users = Import-CSV $batchFile
$totalProfiles = $users.Count
ForEach ($user in $users) 
{
    
    $currentProfile ++;
    $AccountName = $user.USERID
    
    $profile = $upm.GetUserProfile($AccountName)

    try
    {       
        
        forEach ($Property in $Properties)
        {
            $PropertyTitle = $Property.TITLE

            $OldValue = $profile[$PropertyTitle].Value;

            $profile[$PropertyTitle].Value = $null;
            $profile.Commit() 

            $now = [System.DateTime]::Now
            $msg = $now.ToString() +  " : Deleting value from "+ $PropertyTitle +": "+ $OldValue +" for " + $AccountName + " (" +$currentProfile + " of " + $totalProfiles + ")"
            write-host $msg
            WriteLog $msg $logFile

        }
        
    }
    catch [system.exception]
    {
        $msg = $Error[0].Exception.InnerException.InnerException.Message
        write-host -f red $msg
        WriteLog $msg $logFile
    }
        
    $profile = $Null
    $user = $Null
}


$mysite.Dispose(); 


Thursday, March 20, 2014

Compare AD Properties to SharePoint UPA Properties

Scenario: I had a situation where I had to compare the properties of users from Active Directory to User Profile.

Solution:
  1. Export all users from Active Directory to CSV. How?
  2. Export all users from User Profile Application to CSV. How?
  3. Compare columns between two CSV files using the PowerShell script (ADvsUPAValidation.ps1) below.
#
# Author: Tahir Naveed
# Created: Mar 13, 2014
# Modified: Mar 13, 2014
# Description:     
# This script compares AD properties with UPA properties for a user
#
#

function WriteLog
{
    Param([string]$message, [string]$logFilePath)
    Add-Content -Path $logFilePath -Value $message
}

$LogFile = "G:\PowerShellScripts\ADvsUPAValidation\ADvsUPA_Result.log"
$ADFile = "G:\PowerShellScripts\ADvsUPAValidation\ADexport.csv"  
$UPAFile = "G:\PowerShellScripts\ADvsUPAValidation\UPAexport.csv"

$ADProfileCount = 0
$ADUsers = Import-CSV $ADFile | sort sAMAccountName
$TotalADProfiles = $ADUsers.Count


ForEach ($ADUser in $ADUsers) 
{
    $ADProfileCount ++;

    try
    {  
        # Search AD User in UPA
        $UPAUser = Import-CSV $UPAFile | where-object {$_.UserName -eq $ADUser.sAMAccountName}
        
        $Now = [System.DateTime]::Now
        $MSG = $Now.ToString() +  " | Working on "+ $ADProfileCount + " of " + $TotalADProfiles + " - " +$ADUser.sAMAccountName 
        write-host $MSG

        if(($UPAUser.FirstName -ne $null)-and($ADUser.givenName -ne $null)-and($UPAUser.FirstName -ne $ADUser.givenName))
        {
            $MSG = "FirstName mismatch:"+ $UPAUser.UserName + ":UPA:" + $UPAUser.FirstName+ ":AD:" + $ADUser.givenName
            write-host -f red  $MSG
            WriteLog $MSG $LogFile
        }
        if(($UPAUser.LastName -ne $null)-and($ADUser.sn -ne $null)-and($UPAUser.LastName -ne $ADUser.sn))
        {
            $MSG = "LastName mismatch:"+ $UPAUser.UserName + ":UPA:" + $UPAUser.LastName+ ":AD:" + $ADUser.sn
            write-host -f red  $MSG
            WriteLog $MSG $LogFile
        }
        if(($UPAUser.PreferredName -ne $null)-and($ADUser.displayName -ne $null)-and($UPAUser.PreferredName -ne $ADUser.displayName))
        {
            $MSG = "PreferredName mismatch:"+ $UPAUser.UserName + ":UPA:" + $UPAUser.LastName+ ":AD:" + $ADUser.displayName
            write-host -f red  $MSG
            WriteLog $MSG $LogFile
        }

    }
    catch [system.exception]
    {
        $Now = [System.DateTime]::Now
        $MSG = $Now.ToString() + " | "+ $ADUser +" | Exp | " + $_.Exception.Message
        write-host -f red $MSG
        WriteLog $MSG $LogFile
    }

    $User = $Null
}

write-host "Done."

Monday, February 24, 2014

SharePoint 2013 - User Profile Cleanup Timer Job

Diagrams below explain how the user profiles are getting imported by User Profile Application in SharePoint 2013 and then how they are deleted from the SharePoint.

MySites is created when user accesses the MySite Host Site.


After the profiles are marked deleted in the UserProfile_Full table, Cleanup job takes care of the dirty work.



Tuesday, January 14, 2014

Export Sharepoint User Profiles to CSV

I was looking for PowerShell script to export SharePoint User Profile data to a CSV and found this beautiful script by John Lynch.

I have made following little modification to the script:
  1. Export users which have special characters in their name by applying the UTF8 encoding.
  2. Check for manager field and show their display name instead of network id.
# Export Sharepoint User Profiles to CSV file
# Created: John Lynch 2013
# Updated: Tahir Naveed 2014
# MIT License

$siteUrl = "http://MySite.com"
$outputFile = "G:\UPAExport\UPAexport_20140428.csv"

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

Function GetDisplayName($UserName)
{
    $serviceContext = Get-SPServiceContext -Site $siteUrl
    $upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($serviceContext);
    $userProfile = $upm.GetUserProfile($UserName);
    $FullName = $userProfile.DisplayName
    return $FullName
}

$serviceContext = Get-SPServiceContext -Site $siteUrl
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($serviceContext);
$profiles = $profileManager.GetEnumerator()

$fields = @(
            "UserName"
            "FirstName",
            "LastName",
            "PreferredName",
            "WorkPhone",
            "MobilePhoneFromAD",
            "HomePhone",
            "CellPhone",
            "Fax",
            "localTelephone",
            "SPS-Birthday",
            "WorkEmail",
            "PersonalSpace",
            "PictureURL",
            "Office",
            "title",
            "department",
            "manager",
            "SPS-School",
            "PersonalInterests",
            "LocationExperience",
            "HomeTown",
            "Assistant"
)

$collection = @()

foreach ($profile in $profiles) 
{
   $user = "" | select $fields
   foreach ($field in $fields) 
   {    
        if($profile[$field].Property.IsMultivalued) 
        {
            $user.$field = $profile[$field] -join "|"
        } 
        else 
        {
            if ($field -eq "manager" -or $field -eq "Assistant")
            {
                $DomainName = $profile[$field].Value;
                if ($DomainName -ne $null)
                {
                    $DisplayName = GetDisplayName $DomainName
                    $user.$field = $DisplayName
                }
            }
            else
            {
                $user.$field = $profile[$field].Value
            }
        }
       
   }
   $collection += $user
   Write-Host $user.UserName
}

$collection | Export-Csv $outputFile -NoTypeInformation -Encoding UTF8
$collection |  Out-GridView

Monday, November 11, 2013

SharePoint 2013 - Download MySite Profile Picture

Scenario:
There was a requirement to download all the profile pictures from SharePoint 2013 MySite and save them in different folders (based on user's domain name). After downloading images need to be resized to 30x30 pixels.


Solution:
I wrote following command line utility to achieve the goal.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Server;
using Microsoft.Office.Server.Administration;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.SharePoint;
using System.Web;
using System.Net;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Configuration;

namespace MySiteDownloader
{
    class Program
    {
        static string strURL = ConfigurationManager.AppSettings["MySiteURL"];
        static string strDomain = ConfigurationManager.AppSettings["Domain"];
        static string strLogin = ConfigurationManager.AppSettings["Login"];
        static string strPassword = ConfigurationManager.AppSettings["Password"];
        

        static void Main(string[] args)
        {
            Console.WriteLine("MySite Downloader");
            Console.WriteLine("=================");

            GetProfilePictures();

            Console.WriteLine("Press any key to continue...");
            Console.ReadLine();
        }

        static void GetProfilePictures()
        {
            try
            {
                string strAccount = null;
                string strProfilePicURL = null;
                string strFileName = null;
                Uri uri = null;

                WriteLog("Getting user profiles from " + strURL);

                using (SPSite site = new SPSite(strURL))
                {
                    SPServiceContext context = SPServiceContext.GetContext(site);
                    UserProfileManager upm = new UserProfileManager(context);
                    WriteLog("Total user profiles found: " + upm.Count);

                    foreach (UserProfile profile in upm)
                    {
                        strAccount = profile.GetProfileValueCollection("AccountName").ToString();

                        try
                        {
                            strProfilePicURL = profile.GetProfileValueCollection("PictureURL").ToString();
                        }
                        catch(System.Exception ex)
                        {
                            strProfilePicURL = "";
                        }

                        WriteLog(strAccount + " - " + strProfilePicURL);

                        if (strProfilePicURL != "")
                        {
                            uri = new Uri(strProfilePicURL);
                            strFileName = System.IO.Path.GetFileName(uri.LocalPath);

                            DownloadPicture(strProfilePicURL, strAccount.Split('\\')[0], strFileName);
                        }
                    }

                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        static  void DownloadPicture(string strPicURL, string strFolder, string strFile)
        {
            string FilePath = AppDomain.CurrentDomain.BaseDirectory + "\\" + strFolder + "\\" + strFile.Replace("_MThumb", "");

            //File Download

            try
            {
                using (WebClient Client = new WebClient())
                {
                    if (!System.IO.Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\" + strFolder))
                    {
                        System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\" + strFolder);
                    }

                    Client.Credentials = new NetworkCredential(strLogin, strPassword, strDomain);
                    Client.DownloadFile(strPicURL, FilePath);
                }

            }
            catch(System.Exception ex)
            {
                WriteLog(ex.ToString());
            }

            

            //Image Processing

            try
            {
                var image = Image.FromFile(FilePath);
                var newImage = ScaleImage(image, 30, 30);
                newImage.Save(FilePath.Replace("_MThumb", ""), ImageFormat.Png);
                //System.IO.File.Delete(FilePath);
            }
            catch (System.Exception ex)
            {
                WriteLog(ex.ToString());
            }

        }

        public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
        {
            var ratioX = (double)maxWidth / image.Width;
            var ratioY = (double)maxHeight / image.Height;
            var ratio = Math.Min(ratioX, ratioY);

            var newWidth = (int)(image.Width * ratio);
            var newHeight = (int)(image.Height * ratio);

            var newImage = new Bitmap(newWidth, newHeight);
            Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
            return newImage;
        }

        static void WriteLog(string strMessage)
        {
            Console.WriteLine(strMessage);

            string strLogMessage = string.Empty;
            string strLogFile = AppDomain.CurrentDomain.BaseDirectory;
            strLogFile += "MySiteDownloader.txt";
            StreamWriter swLog;

            strLogMessage = string.Format("{0}: {1}", DateTime.Now, strMessage);

            if (!File.Exists(strLogFile))
            {
                swLog = new StreamWriter(strLogFile);
            }
            else
            {
                swLog = File.AppendText(strLogFile);
            }

            swLog.WriteLine(strLogMessage);
            swLog.Close();

        }
    }
}
Note: Image re-sizing code has been copied from internet.

App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <appSettings>
    <add key="MySiteURL" value="http://mysite" />
    <add key="Domain" value="US" />
    <add key="Login" value="Login" />
    <add key="Password" value="Password" />
  </appSettings>
</configuration>

Friday, October 4, 2013

User Profile Properties through JSOM

Following is the code to get the current user's Profile Properties through JSOM (JavaScript Object Model) in SharePoint 2013.
<script src="/_layouts/15/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="/_layouts/15/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/_layouts/15/init.js" type="text/javascript"></script>
<script src="/_layouts/15/sp.runtime.js" type="text/javascript"></script>
<script src="/_layouts/15/sp.js" type="text/javascript"></script>
<script src="/_layouts/15/SP.UserProfiles.js" type="text/javascript"></script>

<script type="text/javascript">

    //$(document).ready(function(){
        SP.SOD.executeOrDelayUntilScriptLoaded(getUserProperties, 'SP.UserProfiles.js');
    //});

    var userProfileProperties;

    function getUserProperties() {

        var clientContext = new SP.ClientContext.get_current();
        var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
        userProfileProperties = peopleManager.getMyProperties();
        clientContext.load(userProfileProperties);
        clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
    }

    // This function runs if the executeQueryAsync call succeeds.
    function onRequestSuccess() {
        var messageText = "<b>";
        if (userProfileProperties.get_userProfileProperties()['Title'] != "")
            messageText += userProfileProperties.get_userProfileProperties()['Title'];
        if (userProfileProperties.get_userProfileProperties()['SPS-Department'] != "")
            messageText += ", " + userProfileProperties.get_userProfileProperties()['SPS-Department'];
        if (messageText.length > 5)
            messageText += "<br/>";
        if (userProfileProperties.get_userProfileProperties()['Office'] != "")
            messageText += userProfileProperties.get_userProfileProperties()['Office'];
        if (userProfileProperties.get_userProfileProperties()['WorkPhone'] != "")
            messageText += ", " + userProfileProperties.get_userProfileProperties()['WorkPhone'];
        messageText += "</b>";
        $get("results").innerHTML = messageText;
    }

    // This function runs if the executeQueryAsync call fails.
    function onRequestFail(sender, args) {
        $get("results").innerHTML = "Error: " + args.get_message();
    }

</script>

<div id="results"></div>

Official SharePoint Documentation

I have recently contributed to the official SharePoint documentation for developement. Check it out here: https://docs.microsoft.com/en-us...