End-To-End SharePoint 2010 User Profile Photos & AD

During a recent WSS3 to SharePoint Server 2010 upgrade, the need arose to move roughly 600 user photos into Active Directory and implement user profile photos for SharePoint. While user photos existed, they were stored in a SharePoint library which would be sunset following the build of the new 2010 environment. Additionally, the user photos needed to be available for a custom web part solution highlighting employee birthdays and anniversaries. Initially, thoughts were to follow the old model and store the photos in a picture library, but with the organization’s IT strategy and upcoming deployment of Lync 2010, using Active Directory as the central repository for photos made the most sense.

Step 1: Getting Photos into Active Directory

There’s a ton of blog posts and articles available on how to use PowerShell and Exchange tools to import photos into Active Directory. Normally I’m the first person to jump on the PowerShell bandwagon, but in this instance there are a few constraints. Pushing thumbnails to AD with this method requires your images to be less than 10kb in size, and a fixed size of 96 x 96px. If you intend to reuse these images outside of Exchange or Lync, you likely want a higher quality of image. You certainly don’t want to be using unedited photos right out of a digital camera, but something more along the lines of a 300px image is going to give you greater quality and reuse.

Due (primarily) to this constraint, we opted to use a third party tool that gave a little more control over the image format and size, while still offering a bulk load ability. We grabbed the trial version of AD Photo Edit from Chris Wright, and put it through it’s paces. The trial lets you execute just 5 users at a time, but once we validated it would do what we wanted we purchased a copy of the full version. At just $49, it’s significantly cheaper than the manual effort of doing this one at a time for 600 users. This particular tool had the ability to specify the naming format of our photos, so we could point it to the folder of 600 photos and it would automatically reconcile to the correct AD user and import the photo. Once you confirm that your photo names conform to a naming convention that matches an AD property, you’re off to the races.

Step 2: Mapping the AD Photo into SharePoint 2010

Once you’ve pushed all of your photos into Active Directory, you must tell SharePoint they are there. By default, SharePoint will not just grab the photos from AD. Head into Central Administration and navigate to your User Profile Service Application. From the main UPS screen, pick “Manage User Properties” and edit the “Picture” property. Set the “Edit Settings” radio button to not allow users to change their photos, ensure that your “Source Data Connection” is set to your Active Directory UPS connection, set the “Attribute” to “thumbnailPhoto” and the “Direction” to “Import”. Finally, click “Add”, then “OK”.

Since UPS didn’t know about this field previously, we must now perform a synchronization and allow UPS to fetch the data for this newly mapped field. From your User Profile Service Application, click “Start Profile Synchronization”, select a full synchronization, then click “OK”. This first synchronization since the field was mapped must be done as a full sync because that field previously was un-mapped. During an incremental synchronization, UPS will update the values for all mapped fields, but it will not look for new ones. Once a full sync completes, incremental will be sufficient for future updating of the individual account details.

If you think back to step one, you’ll remember that we chose this method because wanted a better quality of photo than a 10kb 96px image. As SharePoint will be looking for a specific size to use in thumbnails and user profile pages, we must now tell SharePoint to generate the appropriate sized images from the original in Active Directory. Before you can perform this task, ensure that the user you’re logged in to the SharePoint server with has “Full Control” on the User Profile Service Application. From the main “Manage Service Applications Screen”, select the User Profile Service Application, and then click “Administrators”. Confirm that the account you’re logged in as has the “Full Control” role, and if not add it now.

Next, open a new PowerShell session and run the following commands:

Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0
Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1 -MySiteHostLocation http://mysites

The first command simply loads the SharePoint PowerShell Snapin if you haven’t already loaded it. The second command physically tells UPS to iterate through the photos in the user profiles and generate the thumbnails if they don’t already exist. Obviously if you’ve bulk loaded a large number of photos this will take a few minutes. Be sure to include the correct path to your MySite host. If you get an error about an object reference not set to an instance of an object, you likely have a permissions issue, and the user you’re logged in as doesn’t have full control of UPS.

Once this operation completes you should see user photos in SharePoint. Note that the best way to verify this is to look at the actual personal profile (person.aspx). Performing a search will still show you the old photo (or no photo) until the next incremental search crawl takes place on the content source with your sps3:// provider mapped.

Step 3: Ongoing Maintenance

This is fabulous, I’ve bulk loaded my 600, 1000, 2000 users and we’re up and running; but what happens when I change 10 of my photos tomorrow, or process a new hire next week? First of all, you’ve got to put that user’s photo in Active Directory. Many of the tools that offer bulk loading of photos will also allow you to manage one-off uploads or additions. Once the photo has been added to Active Directory, SharePoint User Profile Synchronization will grab that image on it’s next incremental synchronization (typically nightly). The piece that is most easily forgotten is this: UPS may have that image, but it cannot use it until the thumbnails are generated by running the Update-SPProfilePhotoStore cmdlet in PowerShell. Essentially, that cmdlet needs to be run after every UPS sync completes to ensure that the current photo is actually displayed.

The easiest way to accomplish this is to setup a scheduled task that calls your PowerShell script. First things first, create a new PowerShell script containing the following commands, and save it (ie: C:\Solutions\Update-SPProfilePhotoStore.ps1):

Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0
Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1 -MySiteHostLocation http://mysites
$event = New-Object System.Diagnostics.EventLog("Application")
$event.Source = "SharePoint"
$infoEvent = [System.Diagnostics.EventLogEntryType]::Information
$event.WriteEntry("User Profile Service Photos Updated", $infoEvent, 5000)

Note that the first two lines of this script are identical to our previous execution of the Update-SPProfilePhotoStore cmdlet. The lines after it log the event to the system’s application log using a source application of “SharePoint”, an event description of “User Profile Service Photos Updated”, and an event ID of 5000. We add this simply as a way of verifying that the PowerShell script is actually being run (and at the correct time).

With the script saved, head over to Windows Scheduled Tasks, and create a new task. Set the task to execute a program and provide the path to powershell.exe as well as your script:

c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe "& 'C:\Solutions\Update-SPProfilePhotoStore.ps1'"

Schedule your task to run even if the user is not logged on, and ensure it happens sometime after the nightly User Profile Synchronization Timer Job. For example, if your UPS job runs at 1:00 AM, you may want to schedule your task to fire at 3:00 AM, giving ample time for UPS to finish processing before user profile thumbnails get updated. You must also ensure that the task is executed by a user that has “Full Control” to the UPS service application, or the script will fail to process.

Create SharePoint Groups with PowerShell

@ #SPSVB Could use help coming up w/a script to make 110 SP Groups for 1 Site collection. Have time to help?
@java_woman
Rebecca Ward

It wasn’t until I looked into this tweet that I realized there was no “New-SPGroup” type cmdlet that ships with SharePoint out of the box. Instead, we have to call the SiteGroups.Add operation on the web where we want to make the group. While this isn’t terribly intuitive for people new to PowerShell, this post should help to walk you through it.

Firstly, we’re adding groups to webs, not sites, so we need to identify the web where the group is going to exist. While groups are available site-wide, they’re actually stored at the web level, which explains why when you create a subsite (a web), you get the three default groups created. Yes, I realize it’s confusing that a web has a property of “SiteGroups”, and a site doesn’t–but that’s just the way it is. Before we can do anything, we need to create a variable and save our web object into it.

$web = Get-SPWeb http://intranet

In addition to a title and description, we also need to specify the owner and any members of our group when we call the SiteGroups.Add operation; those users must be valid SPUser objects, not a “domain\username” string. To keep things simple for this example, let’s assume they’re the same person, since the owner is typically also a member of the group. We’re going to create a user variable, and pipe our web object to the Get-SPUser cmdlet (with a user string). This will tell PowerShell to iterate through every user in our web until it finds the one we’ve specified, and save that SPUser object to our user variable.

$user = $web | Get-SPUser "domain\username"

Now that we have our user captured, we can go ahead and call the SiteGroups.Add operation, passing to it the title of the group, the owner of the group, the members of the group, and the description of the group (in that order).

$web.SiteGroups.Add("Group Name", $user, $user, "Group Description")

Now it’s a simple matter of heading on over to your groups list and validating that it’s there.

If, like Rebecca, you had a lot of these to do, you could store the details in a CSV file and handle your inputs from there. Let’s assume you had a CSV with columns of “Web”, “GroupName”, “User”, and “GroupDescription” that was stored in C:\Groups.csv, we can make a simple script to loop through all of the lines in the Groups.csv file and create each group.

$groups = Import-CSV c:\Groups.csv
foreach ($group in $groups) {
	$web = Get-SPWeb $group.Web
	$user = $web | Get-SPUser $group.User
	$web.SiteGroups.Add($group.GroupName, $user, $user, $group.GroupDescription)
}
11
Jan 2012
CATEGORY

Technology

COMMENTS 3 Comments

Making Life Easier with PowerShell (SPSVB 2012)

Have you ever spent an afternoon setting site collection properties manually on every site collection in your farm? How about going through and activating features following an upgrade? These are just two simple examples of where PowerShell can turn an entire afternoon worth of work into just a few minutes. In this session we’ll start off with a familiarization of PowerShell and progress into capabilities and usage scenarios of the out of the box SharePoint 2010 cmdlets.

Presented at SharePoint Saturday, Virginia Beach (January 7, 2012)

Resources:

Making Life Easier with PowerShell (SPSRIC 2011)

Have you ever spent an afternoon setting site collection properties manually on every site collection in your farm? How about going through and activating features following an upgrade? These are just two simple examples of where PowerShell can turn an entire afternoon worth of work into just a few minutes. In this session we’ll start off with a familiarization of PowerShell and progress into capabilities and usage scenarios of the out of the box SharePoint 2010 cmdlets. As presented at SharePoint Saturday, Richmond (November 5, 2011)

Resources:

Validate Application Pools & Identities

I ran into a scenario where I needed to validate what application pool and identity a particular service application was running as. While you can do some round about poking through the UI or through IIS, it’s also pretty simple to grab this information using PowerShell.

Service Applications
First things first, we need to grab a list of all of our service applications. We can skip this step if you already know the name of your service application.

Get-SPServiceApplication

Get-SPServiceApplication will output a list of all service applications configured on your farm. You’ll notice that by default you see three columns (DisplayName, TypeName and Id). As a result of the three columns, PowerShell will truncate the contents of the columns to allow them to all display. This means that if you have long service application names, you probably won’t see the full name. To get around this, we can specify the column(s) we want to see.

Get-SPServiceApplication | Select DisplayName, Id

Once you’ve identified the service application you want to validate (or if you already knew it), we can create a variable containing all of the properties for that particular service application. The “Identity” parameter should match the DisplayName of the service application.

$serviceApp = Get-SPServiceApplication -Identity "My Service Application"

Alternatively, you can also use the GUID to select the service application.

$serviceApp = Get-SPServiceApplication 00000000-0000-0000-0000-000000000000

Now that we have our $serviceApp variable containing all of the properties for our service application, we can view (or set) any of the available properties. The Get-Member cmdlet allows us to view a list of all objects, properties and methods that are children of the current object. In this example, it would list all of the objects, properties and methods of our selected service application.

$serviceApp | Get-Member

We can now determine the application pool and the identity of that application pool by viewing the ApplicationPool property of our service application.

$serviceApp.ApplicationPool

Web Applications
Much like we did with service applications, we first need to identify the web application that we want to work with.

Get-SPWebApplication

Get-SPWebApplication will output a list of all web applications configured on your farm. The nice thing is that web applications are a little more intuitive because we can use the URL of the web application to identify it, and that’s almost certainly something you’re going to know off the top of your head. Once you’ve identified the web application you want to validate, create a variable containing that web application.

$webApp = Get-SPWebApplication http://mywebapp.corp.tld

Just like we did with our service application, we can use the Get-Member cmdlet to list all of the objects, properties and methods of our web application.

$webApp | Get-Member

We can now determine the application pool and the identity of that application pool by viewing the ApplicationPool property of our web application. Note that Microsoft hasn’t been this consistent throughout SharePoint as a whole, and there’s a lot of cases where you’ll find differences between property names on objects where you’d think they would be the same. Learn to love the Get-Member cmdlet, which will always show you what you’ve got to work with.

$webApp.ApplicationPool
18
Sep 2011
CATEGORY

Technology

COMMENTS No Comments

Executing all SharePoint 2010 Health Analyzer Jobs

One of the most useful lines of PowerShell script (as far as SharePoint 2010 goes) has to be the ability to kick off all of the SharePoint Health Analyzer timer jobs in one shot. This single-line of PowerShell is something you should always have in your back pocket, whether you’re validating a newly built farm or performing post-maintenance testing. Once you’ve loaded the SharePoint snapin, simply execute the following line of PowerShell, then surf over to Central Administration to check the farm health.


Get-SPTimerJob | Where {$_.Name -like "*Health*" -and $_.Name -like "*-all-*"} | Start-SPTimerJob
01
Sep 2011
CATEGORY

Technology

COMMENTS No Comments

Understanding Objects, Properties and Methods

As I said in the first post of the series, we will be using PowerShell to interact with SharePoint object model, so we do need to spend a few minutes talking about the differences between an object, a property and a method.

In simple terms, a method can be thought of as a subroutine or a function. Many objects in the SharePoint object model have “precanned” methods attached to them, we’ll come back to this in a later post in more detail.

An object is an element within the object model. Objects are comprised of one or more objects and/or properties. I have always found it useful to conceptually relate objects and properties to XML—objects would be nodes of your XML, and properties would be individual attributes on your nodes. If you were to apply this concept to the photo below:

  • The house is an object
  • The color of the house (blue) could be a property of the house
  • The number of windows (3) could be a property of the house
  • The door could be an object of the house
  • The color of the door (blue) could be a property of the door
27
Aug 2011
CATEGORY

Technology

COMMENTS No Comments
TAGS

An Introduction to PowerShell

This marks the first post in a new series on using Windows PowerShell with SharePoint 2010 (possibly the best marriage of concepts since Hewlett and Packard—a befitting reference given all of the mention of WebOS in the news this week).

In order to take advantage of the true power of PowerShell (no pun intended), you need to have at least a little bit of background on how to get started. While we will be using the SharePoint 2010 object model with PowerShell, you don’t need to be a true developer to take advantage of (some of) the powerful capabilities contained within the beast. As we progress toward the path of writing our own cmdlets and such, the discussion will inevitably turn more dev-focused, but for now let’s focus on the basics.

PowerShell as a Technology

Windows PowerShell is just that, a “Windows” product. In fact, it’s the native Windows management shell, not a technology that’s unique to SharePoint. The nice thing about this is that we can use PowerShell to interact with Windows components, such as services and operating system configuration, in addition to Active Directory, SQL, and other products (including SharePoint).

PowerShell vs. SharePoint Management Shell

If you’ve been poking around on your SharePoint server, you may have noticed that you have two separate shell’s on your system—PowerShell itself, and the SharePoint Management Shell . Aesthetically, the only difference between the two is that the SharePoint Management Shell is black (which gives it more of a command prompt look), and the PowerShell console is actually blue. Both consoles are technically PowerShell, and I’ve got no idea why the SharePoint one is black—unless it was simply to ease the transition from STSADM to PowerShell.

You can open the SharePoint Management Shell from the “Microsoft SharePoint 2010 Products” folder in the start menu. Native Windows PowerShell can be opened either via the PowerShell icon on the task bar, or by navigating to “Accessories” -> “Windows PowerShell” from the start menu.

Functionally, there are a few differences under the covers. When you load the SharePoint Management Shell, it will automatically load the necessary SharePoint components without you having to do any additional steps. In short, you can open it up and fire away. The native PowerShell console won’t (by default) load the SharePoint components, so if I were to open PowerShell and execute something like a simple Get-SPSite command, I’d be greeted with a big red error message saying that it doesn’t know what the Get-SPSite cmdlet is.

So what are these “components” that are being loaded? PowerShell components are broken into two categories: Snapins and Modules. Snapins can be easily loaded by executing Add-PSSnapin and Modules can be loaded by using Import-Module. You can load a snapin anytime you need to, or you can build a custom profile for PowerShell that’ll automatically execute every time you load the console—loading the snapins and modules you frequently use (such as the SharePoint snapin).

27
Aug 2011
CATEGORY

Technology

COMMENTS 1 Comment