April 20, 2011 01:59 PM

Monitor SharePoint User Profile Changes

Two ways to make the user profile change log work for you
SharePoint Pro
InstantDoc ID #129846
Rating: (3)
Downloads
129846.zip

SharePoint Server 2010 is a great platform for storing information about the users in an organization. Using the User Profile Service application and its related components, you can configure SharePoint to store a variety of information about users and synchronize that information with external storage, such as Active Directory (AD) or any other data source to which you can connect using Business Connectivity Services (BCS). Users can then edit their information using the user profile pages. The external storage sources will then be updated automatically with this new information, thereby making the information more relevant and timely throughout the organization.

However, allowing users to update their own information introduces new problems when it comes to governance, particularly in terms of security of information, privacy, and ethical conduct. Fortunately, one component of the User Profile Service application is the User Profile Change Service. The User Profile Change Service isn’t a true service but rather a series of tables within the User Profile Service’s profile database and a timer job (i.e., User Profile Change Cleanup Job) that’s used to clear stored changes older than 14 days. By default, the User Profile Change Cleanup Job runs once a day. You can adjust this frequency by editing the schedule for this timer job.

You can use the User Profile Change Service to view and report on changes. Unfortunately, however, there isn’t a UI to view these changes, so you must use the SharePoint API to query the system to view changes.

But what kind of changes can you query the system for? The answer is simple: all user profile properties. You can see the properties that are available by navigating to the Manage Service Applications page in the Central Administration site, selecting a User Profile Service application, and clicking Manage to view the User Profile Management page. (If a User Profile Service application doesn’t exist, you must create one in order to store and manage user details.) Click the Manage User Properties link to see all the available properties. From here you can create, delete, or edit any properties that you want your users to populate with data. When a user edits any of the values for one of these properties, a change record will be created. However, it’s important to remember that changes will persist for only 14 days, assuming the User Profile Change Cleanup Job is running. If you need to keep these changes longer, you can change the retention period by running a simple STSADM command. (There’s no Windows PowerShell equivalent way to do this.) The following example changes the retention period to 28 days:

stsadm -o profilechangelog

  -userprofileapplication "My User Profile Service App"

  -daysofhistory 28

(Although the command wraps here, you'd enter it all on one line. The same holds true for the other commands that wrap.) You can gain access to these change records using the objects in the Microsoft.Office.Server.UserProfiles namespace, which is part of the Microsoft.Office.Server.UserProfiles.dll assembly. Specifically, you use the UserProfileManager, UserProfileChangeQuery, and UserProfileChangeToken classes.

Retrieving User Profile Changes

To retrieve user profile changes, you must first create an instance of the UserProfileManager class. This class is the gateway for all programmatic manipulations of the user profile properties and their properties. To create an instance of this class, you must provide it with a Microsoft.SharePoint.SPServiceContext object. This context object makes sure that you’re working with the correct User Profile Service application.

There are two ways to retrieve the SPServiceContext object:

  1. You can provide a specific service application proxy object and a site subscription identifier. (Site subscriptions are only relevant in multi-tenancy scenarios. Most users can use the default site subscription, which is essentially just an empty globally unique identifier—GUID.)
  2. You can provide a site collection that’s associated with the service application.

Listing 1 demonstrates the first approach using PowerShell. Alternatively, you could use code in which the URL to the site collection is passed to the GetContext method. Either approach is perfectly acceptable.

Now that you have the SPServiceContext object, you can create the UserProfileManager object:

$manager = New-Object Microsoft.Office.Server.

UserProfiles.UserProfileManager $context

The UserProfileManager class contains the GetChanges method. This method has three overloads:

  • GetChanges(), which retrieves all changes
  • GetChanges(UserProfileChangeToken), which retrieves all changes from a given date or event
  • GetChanges(ProfileBaseChangeQuery), which retrieves specific changes given a query object

All the GetChanges overloads return a UserProfileChangeCollection object. This object contains all the changes stored as either a UserProfileChange object or one of its derivative types:

  • UserProfileColleagueChange
  • UserProfileCustomChange
  • UserProfileLinkItemChange
  • UserProfileMembershipChange
  • UserProfileOrganizationMembershipChange
  • UserProfilePropertyValueChange
  • UserProfileWebLogChange

Each object type stores the resultant change in a manner most appropriate for the given type. It’s important to note that a separate object will be returned for every change. So, if a user edits two profile properties, you’ll have at least two objects (one for each property). As the phrase “at least” implies, you could have more than two objects. For example, if the user edits the Skills property by adding several skills, a separate change object will be returned for each skill added (i.e., one object for each value entered).

Using the GetChanges Method

Let’s look at examples of how to use each overload for the GetChanges method. Figure 1 shows an example of running the GetChanges() method without any parameters. Running the method in this manner will return all changes in the log, which can be quite numerous.

Figure 1: Example of the GetChanges() method
Figure 1: Example of the GetChanges() method

You can reduce the number of changes returned by passing in a UserProfileChangeToken object to the GetChanges method. This object lets you retrieve changes starting from a specific date. To do so, you simply specify that date in the change token.

You can also retrieve all the changes created after a certain change event. In this case, you need to specify an arbitrary date and the change event’s ID because there’s no constructor available that accepts only an event ID. Only the event ID will be used; the date will be ignored.

Figure 2 shows an example of running the GetChanges method when you pass in a UserProfileChangeToken object with both the event ID (value of 32) and date ($date, whose value is 1/31/2011) set. Alternatively, you could provide a value of [System.DateTime]::Now for the $date variable, as the value itself is irrelevant when the event ID is provided. (Note that the UserProfileChangeToken object values can only be set by initializing the object through its constructors.)

Figure 2: Example of the GetChanges(UserProfileChangeToken) method
Figure 2: Example of the GetChanges(UserProfileChangeToken) method

Filtering in this manner, however, can still result in a large number of records returned, particularly if you’re only interested in a specific type of change. To address this concern, you can use the third GetChanges overload and pass in a UserProfileChangeQuery object. This object gives you the ability to specify exactly what type of changes you want returned. For example, perhaps you only want to know when single-valued properties (such as the AboutMe property) are added or updated. Using the UserProfileChangeQuery object, you can specify what property types and change types you care about.

The UserProfileChangeQuery object’s constructor lets you quickly set all the filtering properties to false. You can then enable just the properties of interest by setting them to true. For example, the code in Figure 3 sets all the properties to false when it initializes the UserProfileChangeQuery object, then sets the SingleValueProperty, Add, and Update properties to True.

Figure 3: Example of the GetChanges(ProfileBaseChangeQuery) method
Figure 3: Example of the GetChanges(ProfileBaseChangeQuery) method

As you can see, retrieving user profile changes is fairly simple, requiring knowledge of only a few classes and their various members. With PowerShell, you can easily format the returned data a variety of ways. For example, Figure 4 shows Figure 3’s query results formatted into tables and grouped by account.

Figure 4: Example of formatted query results
Figure 4: Example of formatted query results

 

Empowering Privileged Users to Monitor Changes

Using PowerShell to retrieve information about user changes can be extraordinarily powerful and useful to administrators. But to enforce governance policies, you must bring the ability to monitor changes to privileged users (e.g., HR staff members) and give them the responsibility and authority to properly act on this data. Let’s examine a real-world example that accomplishes the goal of empowering privileged users.

Suppose that an organization’s HR department has employee policies set in place that govern the communications of employees for email and other types of communication. These policies are extended to the communications in employees’ personal sites and their user profile information. The HR department wants to monitor updates to visible fields like About me to ensure that the employees are complying with the policies. Further, it wants to have the freedom to review the changes from a central location and receive an alert when a new change has been posted to the change log.

The HR department’s requirements are easy to achieve if you consider that once you’ve gathered the changes and stored them in a list that HR staff members have access to, they can manage the information and set alerts using the list’s functionality. The only customizations you need to write are:

  • A SharePoint timer job that queries the log on a regular basis and adds the query results to the list
  • An administrative UI to manage the timer job

In this example, the list resides at the root of the My Site host, but the list could reside anywhere in a real implementation.

Creating the Timer Job

Let’s walk through the code that creates the SharePoint timer job to see how it works. This example is based on the Microsoft article “Creating Custom Timer Jobs in Windows SharePoint Services 3.0”.

The timer job begins by creating an instance of the UserProfileWatcherTimerJob class, which inherits from the SPJobDefinition class. The SPJobDefinition class has a property bag that lets you provide properties to the Execute method for processing. In this case, the SubmitJob method is used to pass the userProfileFields and mySiteHost properties to the timer job instance and store them in the property bag, as you can see in the code that Listing 2 shows.

The Execute method is called when the timer job runs. As seen in Listing 3, the Execute method begins by reading the values of the timer job’s properties. Next, it creates an instance of the worker class, UserProfileWatcherWorker, passing in those values. UserProfileWatcherWorker then provides two methods, which the Execute method uses to query the user profile change log and update the target list when changes matching the query are found.

Related Content:

ARTICLE TOOLS

   
Comments
  • Srikanth
    11 months ago
    Jun 17, 2011

    Hi,
    I tried to change the retention period to one day using the powershell command stsadm -o profilechangelog -userprofileapplication "My User Profile Service App" -daysofhistory 28 but didnot work.

    can we reduce the retention period to less than 14 days or not ?

You must log on before posting a comment.

Are you a new visitor? Register Here
   
   

Dan Holme's Viewpoint on SharePoint Blog

Office 365 Plan for Pain

With cloud services, even Office 365, what you don’t know about your cloud service can hurt you,...

SharePoint News and Products

Let SharePoint Be SharePoint: Making Social Collaboration Secure

Hesitant about unleashing SharePoint's social features? SharePoint security vendors aim to help....

Dan Holme's Viewpoint on SharePoint Blog

Microsoft SkyDrive Updates in the News

Microsoft's cloud storage, sharing, and collaboration platform for Windows Live is updated,...