Adding XPS indexing to SharePoint

It's pretty simple to add XPS indexing/support to a SharePoint 2010 search, but even so some people struggle. So just to make things real easy for you, I created a PowerShell script.
What you need to do:
  1. Logon to the server that's running SharePoint Server Search 14
  2. Copy the PowerShell script from below (some of it runs under right navigation)
  3. Paste it in to a text file > save as whatever.ps1.
  4. Run the PowerShell script.

Import-Module servermanager $xps = Get-WindowsFeature XPS-Viewer If ($xps.Installed -eq $FALSE) { Add-WindowsFeature XPS-Viewer } If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null) { $PSSnapin = Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null } Write-Host -ForegroundColor White "- Adding registry values ..." New-Item -path "HKLM:\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\Filters\.xps" New-ItemProperty "HKLM:\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\Filters\.xps" -Name "Extension" -value "xps" -PropertyType String -Force | Out-Null New-ItemProperty "HKLM:\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\Filters\.xps" -Name "FileTypeBucket" -value "1" -PropertyType dword -Force | Out-Null New-ItemProperty "HKLM:\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\Filters\.xps" -Name "MimeTypes" -value "application/xps" -PropertyType String -Force | Out-Null New-Item -path "HKLM:\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\ContentIndexCommon\Filters\Extension\.xps" New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\ContentIndexCommon\Filters\Extension\.xps" -Name "(Default)" -value "{1E4CEC13-76BD-4ce2-8372-711CB6F10FD1}" -PropertyType MultiString -Force | Out-Null Get-SPEnterpriseSearchServiceApplication | New-SPEnterpriseSearchCrawlExtension "xps" Stop-Service "OSearch14" Start-Service "OSearch14"


Stop MySite from being deleted.

The My Site of [USER] is scheduled for deletion.
The My Site of [USER] is scheduled for deletion in 3 days. As their manager you are now the temporary owner of their site. This temporary ownership gives you access to the site to copy any business-related information you might need. To access the site use this URL: http://mysites/personal/[USER]

  • User profile deleted
  • User profile re-imported
  • User profile has its Personal site property missing
There's a Timer Job that runs every hour called My Site Cleanup Job. This job among other things looks at dbo.Profile_DeletedUsers and My Sites that don't have a current user profile association.
When it finds a My Site without a user profile association it adds the site to the dbo.MySiteDeletionStatus table in the Profile DB.

  • Ensure the User Profile has the site associated with his account
  • The following query will give you profiles with a My Site.
    SELECT PropertyVal, p.* FROM dbo.UserProfileValue v inner join dbo.UserProfile_Full p on p.RecordID=v.RecordID where PropertyID=22 and PropertyVal is not null
    If the account isn't there you need to go to: Central Administration > Manage User Profiles and add the URL to the Personal site property.
  • Delete the MySiteDeletionStatus record.
    This table has a NotificationStatus column with values 1-3 calculated based on the Created column.
    1 = 14 days til deletion email, 2 = 3 days til deletion and 3 = 1 day til deletion.
    This last step is the only crucial one.
BTW: This theoretically will leave the Db in an unsupported state, because we're not supposed to edit or even query SP DB's directly... so don't tell anyone and no one will know.


Could not find stored procedure 'proc_UpdateStatisticsNVP' June CU 2011


Log Name:      Application
Source:        Microsoft-SharePoint Products-SharePoint Foundation
Date:          15/07/2011 12:00:31 AM
Event ID:      5586
Task Category: Database
Level:         Error
User:          ray
Computer:     SPS2010
Unknown SQL Exception 2812 occurred. Additional error information from SQL Server is included below.

Could not find stored procedure 'proc_UpdateStatisticsNVP'.


After the June 2011 CU I started getting this error every night in the logs.
A quick search through \Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\SQL
showed [dbo].[proc_UpdateStatistics] was calling this proc.

So I assume where ever I find [dbo].[proc_UpdateStatistics] I should also find [dbo].[proc_UpdateStatisticsNVP]


The fix requires that each DB that has [dbo].[proc_UpdateStatistics] also have [dbo].[proc_UpdateStatisticsNVP] the following SQL Query will help you identify the DB's:

exec sp_msforeachdb 'if exists(select name from [?].sys.objects where type = ''P'' and name like ''%proc_UpdateStatistics%'') AND not exists(select name from [?].sys.objects where type = ''P'' and name like ''%proc_UpdateStatisticsNVP%'') select ''?'''

This will give you the DB's that have [dbo].[proc_UpdateStatistics] but don't have [dbo].[proc_UpdateStatisticsNVP] then all you need to do is create the proc using an existing one...


Migrating documents to SharePoint the easy way

OK, easy is relative, but it if you don't mind making a couple XML configuration files, it's as easy as easy gets with Folders2SP PowerShell script.

Folders2SP Codeplex Project

Before writing the script I evaluated a number of products, but I found non offered the flexibility I wanted and at ~$2500 I reasoned I could do better; hence Folders2SP. Sure it doesn't have a UI and it doesn't support Permission migration... but it's free, 42kb, doesn't soil your production servers, no custom web services (for item level permissions) and you can extend it to your hearts content... so you can add a permissions method.


Folder2SP.ps1 is a PowerShell script which helps you migrate documents from SharePoint and folder structures to SPS2010 while preserving versions, metadata and converting folder names to managed metadata terms.
Use case: You have documents in a MOSS library and in a network share folder structure which need to be migrated to a SPS 2010 library. You want to use the words in the folders as taxonomy terms in your SPS2010 library and perform regular expressions on the file name/path.

Case setup

In this example we're going to get some documents from MOSS document library "Documents", and along with the sample documents included in this package upload them to a "Codeplex" document library in a SPS2010 site.

  1. Create a working directory either on the SPS2010 server or a network share Eg: C:\Folders2SP.

  2. Extract the contents of this project to your working directory. You should have Folders2SP.ps1, run.ps1, codeplex.xml and a "files" directory with some more directories and text files.

  3. Create a destination document library in you SPS2010 site eg: Codeplex.

  4. Add the required fields to the document library eg: Year (choice with 2008-2011), Enterprise Metadata field (site settings > Enterprise Metadata and Keywords Settings), LibMeta1 (Managed Metadata single), LibMeta2(Metadata multi), LibMeta3(Metadata multi) and connect them to an appropriate termset or term.

    • Modify the example codeplex.xml. Use your own MOSS library (works with a SPS2010 document library too).
    • Lookup site: the site you want to get the documents from. The script uses web services. To interrogate the source site I recommend you try my FireWS script , cos it rocks.
      library: the library to get the files from.
      view: if you want specific files, enter the view Guid here.
      rootfolder: is the folder to look in... default is the name of the library.

    • Target site: is the only attribute you need to change for this demo.

    • The xml file is commented so you know the options.

Process overview

  1. Run PowerShell as Administrator (make sure your execution policy is set to remote) from your SPS2010 server, run.ps1 includes Folder2SP.ps1 and calls the function Folder2SP passing Codeplex.xml as the configuration file.

  2. Folder2SP loads the config file, assigns a bunch of variables and creates a log file.

  3. Goes to http://spsdev/documents and starts traversing the library... if you get access denied, it's your fault, try running the scripts from C:\ or use a local MOSS library.

  4. Downloads all files it finds to the "Folders" path

  5. Loops through all the files in Folders path and (if replicatefolders=true) recreates the folder hierarchy on the SPS document library.

    • Connects the Lookup site

    • Gets Metadata

    • Downloads versions to the working directory

    • Uploads the file to the Target document library

    • Loops through each field and check if it's configured in the xml config file. This is an inefficient way of doing it, but the script started out as just a way to copy all field data from the Lookup to the Target.

    • If it's a taxonomy field, it looks up the value, if it can't find the value it creates it. There are a couple options here, so read the comments in the example xml config file.

    • It then loops through the "Field" "Value"s and performs logic associated with Value type. I've only created 3 Value types "FileDate" uses properties from the file, "RegEx" takes an expression and matches on the full file name, and "Lookup" uses a value from the Web Service call.

    • If there's a user field it will 1st attempt to find the user, if it can't find them it will attempt to add them, if that fails it uses the account who's running the script.

    • Sets the new item value.

  6. At the end you should have a migration report, and all the files from the Lookup site and your Folder path in the SPS2010 library with the metadata.

To do

  1. View Fields ($wsFields) for the web service call should be moved to the XML config file.

  2. Permissions could be also migrated if a item level permissions web service were available on the Lookup server.

  3. Improve error handling, and more consistent variable naming.

  4. Improve xml config file

  5. Add more field type handlers


Getting BeforeProperties and AfterProperties in Event Receivers

You're here because you're trying to find away of comparing values of a record before or after saving it in an event receiver, and BeforeProperties and AfterProperties are giving you null, right? Well chances are you searched and found posts about saving the values to a cache, and a lot of other rubbish... I know I did.

Anyway the proper way of doing things is real simple, and I stumbled upon it using Powershell to check my event receivers.

SPEventReceiverDefinition has a Synchronization property.

An Asynchronous event passes the objects to another thread and you lose the BeforeProperties and AfterProperties.
A Synchronous event keeps the thread and you can access the BeforeProperties and AfterProperties.

In my case after specifying the event receiver as Synchronous I was able to compare existing values with values in properties.AfterProperties on an Receiver Type = ItemUpdating.

So to set a Receiver as Synchronous, just add Synchronous to your definition (elements.xml) or in code set the Synchronization property.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">


Starting the User Profile Synchronization Service

Hello my friend!
Me and you obviously have something in common; we've experience the joy of configuring SharePoint 2010's User Profile Synchronization Service.
You've read all the other blog post's and now you're here. There isn't much I can tell you that you probably haven't read... most of the issues are caused by not following Microsoft instructions: http://technet.microsoft.com/en-us/library/ee721049.aspx#StartUPSSProc, and the fact that Forefront Identity Manager (FIM) is a PoS :)

One of the most important lines is: After the User Profile Synchronization service is started, the farm account is no longer required to be an administrator on the synchronization server. To improve the security of your SharePoint Server installation, remove the farm account from the Administrators group on the synchronization server. 

That means the account HAS to be in the local Administrators group before you can start it.

Other things to take in to consideration:

  1. In a multi-server farm "Network Service" and SP account which is starting the User Profile Synchronization Service should also have (Component Services) Local Launch and Activation rights on:
    1. Forefront Identity Manager Controller Object {36574FCB-E5F2-4C55-AA06-146B2B8FBD95}
    2. Forefront Identity Manager Management Agents {10B6A600-6EE8-44F3-AC02-2CA42B08A2B5}
    3. Forefront Identity Manager Script Host Loader {76032766-22CF-497D-BA0D-4F0583F05D15}
    4. Forefront Identity Manager Synchronization Service {835BEE60-8731-4159-8BFF-941301D76D05}
  2. A quick way to make sure your account has rights to launch FIM Synchronization Service is to login using the account and run C:\Program Files\Microsoft Office Servers\14.0\Synchronization Service\UIShell\miisclient.exe
  3. Verify there is only 1 ForefrontIdentityManager Trusted Root Certificate
    Winows Key + R (run): mmc > Ctrl + M > Certificates > Add > Computer Account > Local
    If there are more delete ALL of them and restart the service from Central Admin.
  4. Verify that both ForeFront Identity Manager services are set to Automatic and the Log On As identity is your SP account.
  5. Make sure the SP account is an owner or at the very least FIM_SynchronizationService of  the User Profile Sync DB's
  6. Give the "Network Service" account read/execute rights to "C:\Program Files\Microsoft Office Servers\14.0" directory.
  7. Check the Application Pool is running and/or Recycle it.
    It will be the App Pool which is running "C:\Program Files\Microsoft Office Servers\14.0\webservices\Profile"
  8. Try reinstalling FIM it's in your SP2010 install
    There's an update in the December 2010 CU "pplwfe-x-none.msp"
  9. If you have set NetBiosDomainNamesEnabled on the User Profile Service application to True you may get Error: Unable to process Create message when you try a new Configure Synchronization Connection if you installed the SP2010 December 2010 CU; in this case you're stuffed and it's broken until MS release the Feb 2011 CU.
    To enable netbios names read: http://blogs.msdn.com/b/spses/archive/2010/04/01/sharepoint-2010-provisioning-user-profile-synchronization.aspx
  10. User Profile Synchronization Service suck on "Starting"
    Try running the "ProfileSynchronizationSetupJob" timer job, then check the Timer Job Status page... chance are the Progress is 0%
    I've had this issue and I went home came back the next day and it was done.
  11. ProfileSynchronizationSetupJob is stuck on "Pausing"... Delete the Timer service cache.
  12. If you've tried all of the above it's now time to do what you've been holding out on... yup trawl through the damn logs.
    1. Read: http://blogs.msdn.com/b/spses/archive/2010/12/02/guide-to-user-profile-service-application-upa-part-2-setting-up-the-user-profile-service-application.aspx
    2. Enable verbose logging for the Microsoft.ResourceManagement.Service.exe and SharePoint Portal Server > User Profiles
  13. Don't be afraid of restarting the server... with any luck it might all just work after.