Category: SharePoint

  • SQL Server 2012 SP1 Reporting Services Add-In for SharePoint installation fails with error 1603 – SOLVED!

    SQL Server 2012 SP1 Reporting Services Add-In for SharePoint installation fails with error 1603 – SOLVED!

    Oh, the depths of the nuances found in SharePoint.

    While setting up a new SharePoint 2013 farm that included the Business Intelligence components, we were not able to get the Reporting Services Add-In to successfully install.  The installer would run all the way through, then roll back the entire thing and show this:

    Failed Install

    Looking to the log of the installer, here’s what we found:

    2014-01-08 11:27:54: User: svc_sp2013farmadmin
    2014-01-08 11:27:54: Installing Report Server feature.
    2014-01-08 11:27:58: Beginning uninstall of cab files.
    2014-01-08 11:27:58: Cab files uninstalled successfully.
    2014-01-08 11:27:58: Calling copyappbincontents command.
    2014-01-08 11:28:52: SharePoint Products Configuration Wizard version 15.0.4420.1017. Copyright (C) Microsoft Corporation 2012. All rights reserved.

    Performing configuration task 1 of 3
    Initializing SharePoint Products configuration...

    Successfully initialized the SharePoint Products configuration.

    Performing configuration task 2 of 3
    Installing the application content files...

    Installing the SharePoint Central Administration Web Application content files...

    Installing the SharePoint Web Application content files...

    Failed to install the application content files.

    An exception of type System.NullReferenceException was thrown. Additional exception information: Object reference not set to an instance of an object.

    Total number of configuration settings run: 2
    Total number of successful configuration settings: 1
    Total number of unsuccessful configuration settings: 1
    Successfully stopped the configuration of SharePoint Products.
    Configuration of SharePoint Products failed. Configuration must be performed before you use SharePoint Products. For further details, see the diagnostic log located at D:\SharePointLogs\PSCDiagnostics_1_8_2014_11_27_58_106_1169585150.log and the application event log.

    I swear Object reference not set to an instance of an object is the most infuriating error message ever created.

    We also were getting an event log entry.

    Failed to install the application content files.
    An exception of type System.NullReferenceException was thrown. Additional exception information: Object reference not set to an instance of an object.
    System.NullReferenceException: Object reference not set to an instance of an object.
    at Microsoft.SharePoint.Administration.SPAspConfigurationFile.ApplyActionToXmlDocument(XmlDocument xdAction, XmlDocument xd, String sourceFileName, SupportedXmlDocutmentActions supportedActions)
    at Microsoft.SharePoint.Administration.SPAspConfigurationFile.MergeWebConfig(XmlDocument xdWebConfig, String fileMask)
    at Microsoft.SharePoint.Administration.SPWebService.ApplyApplicationContentToLocalServer()
    at Microsoft.SharePoint.PostSetupConfiguration.ApplicationContentTask.Run()
    at Microsoft.SharePoint.PostSetupConfiguration.TaskThread.ExecuteTask()

    After a bit of searching I finally came across this thread on MSDN, which suggested (of all things) to remove any Comments from the web.config files for my web applications.  Odd, but worth a try.

    I found the following in the web.config for my MySites web application.  I don’t remember commenting that line out, but I went ahead and removed the comments and saved the file.

    <modules runAllManagedModulesForAllRequests="true">
    <remove name="AnonymousIdentification" />
    <remove name="FileAuthorization" />
    <remove name="Profile" />
    <remove name="WebDAVModule" />
    <!--<remove name="Session" />-->
    ...
    </modules>

    I then re-ran the Installer for Reporting Services, and sure enough, it finished successfully.

    Given that the comment is legitimate XML markup it seems odd that the SharePoint Configuration Wizard would choke on it.  But nevertheless, I’m past this issue an on to the next one.

  • Responsive Design with Bootstrap in SharePoint 2010

    Responsive Design with Bootstrap in SharePoint 2010

    It was a real pleasure and privilege for me to present to the Triangle SharePoint User Group this month.

    In my presentation, I demonstrated how to incorporate the Bootstrap web application framework in to SharePoint master pages and page layouts in order to deliver a responsive browsing experience.

    The full video of my presentation is up on Youtube, and shown below.

    (Note: Unfortunately, when I switched from slides to the demo, and switched the display on my laptop from ‘Extend’ mode to ‘Duplicate’ mode, SnagIt didn’t pick up on the transition and the demo portion did not get recorded properly. Thankfully the code can be seen in the video up on the projection screen.  If anyone has specific questions or wants code samples, just add a comment for this post or send me a tweet.)

  • Could not find the taxonomy group error during Visual Studio deployment

    Could not find the taxonomy group error during Visual Studio deployment

    term-store

    We recently updated a SharePoint branding solution to have a custom content type which included Managed Metadata fields.

    When I attempted to deploy this solution to my development farm, however, I got this error when trying to Activate the feature:

    Count not find the taxonomy group Parameter name: name Actual value was Global.

    The cause was that I had not set up the Managed Metadata term store yet with the term hierarchy referenced in the custom content type.  Once I created the Group and Term Sets to match our production environment, the deployment and activation succeeded.

  • Update User Profile photo using Workflow

    Update User Profile photo using Workflow

    Update: I’ve added a video walkthrough of this technique.

    In my last post, I talked about using a Powershell script to import user profile photos from a SharePoint Picture Library in to the MySites users profile.

    That works great to sync up the photos from the library as a batch.  But what happens when you add a new employee photo to the library?  We need something to automatically update the MySite user profile, and a custom workflow will do just that.

    Here’s the general logic for our workflow:

    When an item is added or updated,

    1. Check if a User Name has been set.  If so, 
    2. Retrieve the User’s Profile
    3. Set the ‘PictureUrl’ value to the Url of the item in the picture library.
    4. Save the Profile record.
    5. Regenerate the Thumbnail sizes used by MySites.

    Unfortunately, out of the box, SharePoint Designer workflows will not allow you to manipulate the User Profile.  I made an attempt to use the Virto Software Workflow Activities add-on, but was not able to get it working as I expected.  (UPDATE: This may have been a permissions issue. YMMV)

    So, we need to use a Visual Studio Sequential Workflow in order to get full access to the User Profile.  Here are the steps.

    First, create a new Sequential Workflow project in Visual Studio and go through the wizard

    01_NewProject

    02_ProjectWiz-1

    03_ProjectWiz-2

    04_ProjectWiz-3

    05_ProjectWiz-4

    Next, with the Workflow Designer open, select a ‘Code’ element from the Toolbox and drag it on to the workflow after the onWorkflowActivated1 event.

    06_WorkflowToolbox

    View the Properties for the Code element, and set the ExecuteCode property to “UpdateUserProfilePhoto”.  This will stub out a new method for you in the code file.

    07_SetExecuteCode

    Now, add the following references to your project:

    • Microsoft.Office.Server (14.0.0.0)
    • Microsoft.Office.Server.UserProfiles (14.0.0.0)
    • System.Web (2.0.0.0)

    08_AddReferences

    In your workflow code file, add the following using statements

    using Microsoft.Office.Server.UserProfiles;
    using Microsoft.SharePoint.Administration;
    using System.Web;

    And then add this code to the UpdateUserProfilePhoto method to implement our workflow sequence.

    private void UpdateUserProfilePhoto(object sender, EventArgs e)
    {
      try
      {
    
        //get username
        Microsoft.SharePoint.SPFieldUser fieldUser =
         (Microsoft.SharePoint.SPFieldUser)workflowProperties.Item.Fields.GetField("User Name");
    
        Microsoft.SharePoint.SPFieldUserValue fieldUserValue =
          (Microsoft.SharePoint.SPFieldUserValue)fieldUser.GetFieldValue(workflowProperties.Item["User Name"].ToString());
    
        if (fieldUserValue != null)
        {
          string username = fieldUserValue.User.LoginName.ToString();
    
          if (!string.IsNullOrEmpty(username))
          {
    
            //get profile record
            using (SPSite site = new SPSite(workflowProperties.SiteId))
            {
              SPServiceContext context = SPServiceContext.GetContext(site);
    
              UserProfileManager profileManager = new UserProfileManager(context);
    
              UserProfile profile = profileManager.GetUserProfile(username);
    
              //Updates values
              profile[PropertyConstants.PictureUrl].Value = workflowProperties.Item["EncodedAbsUrl"].ToString();
    
              //commits changes
              profile.Commit();
    
            }
          }
        }
      }
      catch (Exception ex)
      {
        //write to ULS
        SPDiagnosticsService diagSvc = SPDiagnosticsService.Local;
    
        diagSvc.WriteTrace(0, new SPDiagnosticsCategory("Workflow", TraceSeverity.Monitorable, EventSeverity.Error), TraceSeverity.Monitorable,
          "Error in Save User Profile Photo workflow: {0}", new object[] { ex.Message.ToString() });
        diagSvc.WriteTrace(0, new SPDiagnosticsCategory("Workflow", TraceSeverity.Monitorable, EventSeverity.Error), TraceSeverity.Monitorable, 
          "Error in Save User Profile Photo workflow: {0}", new object[] { ex.StackTrace.ToString() });
      }
    }

    Note that there are some slight variations between this code and the Powershell script, namely in the Encoded Absolute Url property name, and the property used to get the username value.

    The workflow is now ready to be deployed, so you can update the Feature and Package to your liking.

    There is one more crucial task in order to make this work, and that is to grant permissions for modifying the User Profile to the Application Pool service account for the web application in which this workflow will run. If you do not do this, you will receive the following exception when the workflow attempts to modify the profile record.

    Attempted to perform an unauthorized operation.
     at Microsoft.Office.Server.UserProfiles.UserProfileValueCollection.CheckUpdatePermissions()    
     at Microsoft.Office.Server.UserProfiles.ProfileValueCollectionBase.set_Value(Object value)    
     at SaveUserProfilePhoto.Workflow1.Workflow1.UpdateUserProfile(Object sender, EventArgs e)

    To grant this permission, go to the Manage Service Applications page in the Central Administration site. Select the entry for the User Profile Service Application, and click the Administrators button shown in the Ribbon.

    Add the application pool service account, then check ‘Full Control’, and save the changes.

    Running the Workflow

    To test the workflow out, we’ll add a new image to our Photo Library, being sure to select a person in the User Name field.  We also need to make sure we Check In the record, since workflow will not run on a checked out item.

    09_AddNewPhoto

    Clicking on the item and viewing its Workflow status will let us see if the Workflow ran successfully.

    11_WorkflowStatus

    Finally we can go to the user’s MySites profile page and confirm that the image is in place.

    10_MySitesProfileWithPhoto

    If the workflow code encounters any exceptions, they will be logged to the ULS file, so you can check there to see what happened.

  • How to Import user photos in to MySites profile

    I’ve come across several SharePoint installations where the HR department has used a Picture Library to store employee headshots.

    The frequent request is how to get those images on to the user’s MySites profile so they appear in search results and permissions lists. This post will walk through the process I used to pull the Image url from the Pictures Library and update the user’s profile using Powershell.

    Associate Picture Library record to a user name

    The first thing that is needed is a way to identify the Photo according to the employee. The simplest way to do this is by adding a ‘Person or Group’ column to the Photo Library Content Type. This column will let you use the People Picker to select their domain account, which is exactly what is needed to retrieve their MySites profile record.

    Add-Username-column

    Powershell Script

    The script is pretty straight forward.  Connect to the Picture Library, iterate through each entry, and for each one retrieve and update the User Profile record.  (The script below is adapted from what is found here.)

    The trick comes mostly from extracting the Domain user name from the column we just added.

    Add-PSSnapin Microsoft.SharePoint.Powershell
    
    #Site URL
    $mySiteUrl = "https://mysites.contoso.com/"
    #The picture library site/web Url
    $pictureLibUrl = "https://sara2.contoso.com/HumanResources/"
    #The name of the picture library 
    $pictureLibName = "Staff Photos"
    #The internal name for PictureURL property on Profile
    $profilePictureURLAttribute = "PictureURL"
    #The internal name for Login property on Profile
    $profileLoginAttribute = "AccountName"
    
    #Get site objects and connect to User Profile Manager service
    $site = Get-SPSite $mySiteUrl
    $context = Get-SPServiceContext $site
    $profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
    $profiles = $profileManager.GetEnumerator()
    
    #Get web object and connect to Picture Library
    $web = Get-SPWeb $pictureLibUrl
    $gallery = $web.Lists[$pictureLibName]
    
    write-host $gallery.ItemCount.ToString() "photo records found."
    
    foreach ($photo in $gallery.Items ) {
    	#get user assigment from column
    	$fieldUser = [Microsoft.SharePoint.SPFieldUser]$photo.Fields.GetField('User Name')
    	$fieldUserValue = [Microsoft.SharePoint.SPFieldUserValue]$fieldUser.GetFieldValue($photo['User Name'])
    
    	if ($fieldUserValue) {
    		$username = $fieldUserValue.User.UserLogin.ToString()
    		if ($username) {
    			#retrieve user's Mysites profile
    			$profile = $profileManager.GetUserProfile($username)
    			if ($profile) {
    				#$photo.url will contain the doc lib path
    				$newPictureUrl = $pictureLibUrl + $photo.Url
    				$profile[$profilePictureUrlAttribute].Value = $newPictureUrl
    				$profile.Commit()
    				write-host "User: " $username "PictureUrl: " $newPictureUrl
    			}
    		}
    	}
    }
    
    #clean up
    $web.Dispose()
    $site.Dispose()
    
    #create thumbnails in Mysites
    Update-SPProfilePhotoStore -MySiteHostLocation $mySiteUrl

    There are two main things to point out. First is using the SPFieldUser and SPFieldUserValue objects to pull out the domain name from the User Name field.

    #get user assigment from column
    $fieldUser = [Microsoft.SharePoint.SPFieldUser]$photo.Fields.GetField('User Name')
    $fieldUserValue = [Microsoft.SharePoint.SPFieldUserValue]$fieldUser.GetFieldValue($photo['User Name'])

    Second is that after you have assigned the Url to the User Profile and saved it, you must run the Update-SPProfilePhotoStore cmdlet in order to properly create the necessary thumbnail images used by MySites.

    #create thumbnails in Mysites
    Update-SPProfilePhotoStore -MySiteHostLocation $mySiteUrl

    Confirm Photo is on MySites Profile

    After running the script, you can confirm the photo assignment by either visiting the user’s MySites profile page, or by editing the profile in Central Admininistration.

  • April 2013 Cumulative Update for SharePoint 2010 breaks Add Web Part dialog

    April 2013 Cumulative Update for SharePoint 2010 breaks Add Web Part dialog

    For a site running on SharePoint 2010, but still using the 2007 user experiences (also known as UIVersion = 3), the April 2013 Cumulative Update for SharePoint 2010 causes the Add Web Part dialog page to break in Internet Explorer.

    After applying the CU, the dialog does not properly resize to display all the available web parts.

    add-web-part-broken

    This problem only occurs in Internet Explorer.

    After reviewing all the Javascript on the page and master page that is supposed to calculate and resize the display, I remembered that the CU had been recently installed.

    Sure enough, when I compared the files to ones on a server that had not received the CU, the files were different.

    Here’s the file from Service Pack 1

    picker-dialog-pre-CU

    And here it is from April 2013 CU.  Based on the file date, it may have actually been the February 2013 CU that introduced the change.

    picker-dialog-post-CU

    To see what exactly had changed, I used Notepad++ to compare the two files.

    picker-dialog-compare

    As can be seen, the 2013 file (on the left) had a new meta tag added to force the display mode for Internet Explorer.  It appears that this caused IE to misreport the content height while resizing the dialog.

    Simply commenting out the extra meta tag allowed the dialog to resize properly in Internet Explorer.

    add-web-part-fixed

    For SharePoint 2010 sites using the 2010 User Experience (that is, UIVersion = 4), this is a non-issue since the Add Web Part selector is part of the ribbon, not in a dialog window.

  • Security trimming the SharePoint Ribbon

    Security trimming the SharePoint Ribbon

    The SharePoint 2010 ribbon control provides various toolbars used by content authors and contributors, particularly when creating and editing Publishing pages.

    But what if your organization doesn’t want to allow certain user groups to change formatting, or select different fonts, in order to maintain a standardized style.  In this case, dynamically changing the ribbon control based on the user’s permissions or group membership allows an organization to determine what and how a user may do while editing content.

    The default Edit Ribbon displays as follows when the user selects an HTML content area:

    default edit ribbon

    Here are the revisions to the ribbon we will make.  Some buttons will be removed altogether, and others will be security trimmed.

    Desired trimmed ribbon

    Creating a custom Ribbon Trimming Control

    To apply the changes to the ribbon, we’ll create a basic control that can be added to the Master Page.  Start by creating a new Empty SharePoint Project in Visual Studio 2010.

    Add references to System.Web and Microsoft.Web.CommandUI.

    Add a class to the project as follows:

    using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint;
    
    namespace MyApp.TrimRibbon
    {
      public partial class RibbonSecurityTrimmer: UserControl
      {
        protected void Page_Load(Object sender, EventArgs e)
        {
          SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);
          if (ribbon != null)
          {
            //remove following controls for all users
            ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Font.Fonts");
            ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Font.FontSize");
            ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Font.FontColor");
            ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Font.FontBackgroundColor");
            ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Markup.LanguagesLabel");
            ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Markup.Languages");
    
            //remove View HTML markup control for anyone who does not have Full Control rights to the site.
            if (!SPContext.Current.Web.DoesUserHavePermissions(SPBasePermissions.FullMask))
            {
              ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Markup.Html");
            }
          }
        }
      }
    }

    Create a Feature to deploy this project’s assembly in to the GAC.

    RibbonTrim Feature

    Be sure to set the Scope to WebApplication so the assembly is globally available.

    Set up the deployment package to include the Feature you just set up.  Keep in mind you’ll need to ensure that a Safe Controls entry is added to the web.config file for the web application during deployment.  

    Deploy to the SharePoint farm and activate the Farm solution.  The assembly should be provisioned in to the GAC (which you can confirm by opening Windows Explorer to c:\windows\assembly.)

    Updating the Master Page

    Open Master Page (either in a branding solution, or using SharePoint Designer)

    Add Register tag before the <html> tag to pull in Assembly.

    <!-- Ribbon Trimming Control -->
    <%@ Register TagPrefix="MyApp" Namespace="MyApp.TrimRibbon" Assembly="MyApp.TrimRibbon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bda84fa329198d63" %>

    Add the control tag in Body section of Master Page.

    <!-- control to trim ribbon -->
    <MyApp:RibbonSecurityTrimmer id="RibbonTrim1" runat="server"/>

    Save and deploy master page.  If you’re using SharePoint Designed, check in and publish your changes.

    To confirm the security trimming is applied, load a page that uses the Master Page you modified, go in to edit mode, and view the revised ribbon.

    Here it is for a user without Full Control rights

    trimmed ribbon

    Here it is for a user with Full Control rights (notice the return of the HTML drop down near the right side.)

    trimmed ribbon full control

    MSDN has a full list of the enumerated SharePoint Permissions and a list of the button control ID values.

    This blog post maps those permissions to the Permission levels typically associated to SharePoint groups.

    Using this approach, you can easily create different variations of the Ribbon for each group of authors, contributors or editors, just by applying different checks using the SPContext.Current.Web.DoesUserHavePermissions method.

    If you need to add additional parameters to control the trimming, you can do that by exposing public properties in your class and setting them in the control tag when you place it on the Master Page.

  • For the love of Pete make your error message meaningful!

    While debugging some custom SharePoint code (not written by me, mind you) today I ran in to this little gem:

    Cannot complete this action.

    Please try again. at Microsoft.SharePoint.Library.SPRequest.MapUrlToListAndView(String bstrUrl, String bstrUrlToMap, Guid& pgListId, Guid& pgViewId)
    at Microsoft.SharePoint.SPWeb.GetListFromWebPartPageUrl(String pageUrl)
    at Microsoft.SharePoint.SPWeb.GetListFromUrl(String pageUrl)
    at MyWebPart.EventCalendars.EventCalendars.GetCalendarUrl(Uri current, Uri referrerUri)
    at MyWebPart.EventCalendars.EventCalendars.CreateChildControls()

    Microsoft is a multi-billion dollar company.  And yet, with all their resources, training, skills and expertise, they still produce an error message that says the equivalent of “I’m broken. Try pressing F5 and see if I am not broken in a few seconds.”

    Is it really that the developers of the SPRequest object in this case don’t actually know what went wrong, so they bubble up this shoulder shrug?

    Or is it that they do know what went wrong, but are embarrassed by it?  Disgusted by it?  Too polite to throw another team under the bus publicly by immortalizing them in an Exception message?

    Who knows.

    Consequences

    When a developer encounters a message like this, the clock begins to tick while a solution is sought out.  With few clues as to what went wrong, that developer has to do more work to find a suitable repair.  More work means more time, more cost, more risk in the project.

    Microsoft can be blamed for project overruns, but they can’t be held directly responsible.  Still, as a standard bearer for the industry, I think they have an obligation to demonstrate the kinds of best practices they advocate.  This error message fails that test with great glory.

    We can do better

    The takeaway lesson here is obviously that if you or your company is creating a consumable API, provide useful feedback.  There’s a little bit of the Golden Rule tied up in this as well – write exception messages for others the way you’d want them to write a message for you.

  • Migration for site failed: Object reference not set to an instance of an object.

    Converting a SharePoint 2010 web application from Classic mode authentication to Claims Mode authentication is fairly well documented.

    After enabling claims mode, it is necessary to use the MigrateUsers() method to reformat the permissions entries in the Content Databases to reflect the Claims mode format.

    I have done several such conversions before without error, but this past weekend I tried another one for a client and ran in to an unusual error.

    The Web Application contained 3 content databases, and 4 site collections.

    The MigrateUsers call appeared to run successfully, and it reported no errors to the Powershell session.

    As we were testing access to the site collections, however, it became clear that one of the site collections had not been converted.

    In reviewing the ULS logs, the following entry revealed that an error had occurred during the run of the MigrateUsers method:

    Migration for site <null> failed: Object reference not set to an instance of an object.
    at
    at Microsoft.SharePoint.Administration.SPWebApplication.LogMigrationError(String name, String objectType, Exception e)
    at Microsoft.SharePoint.Administration.SPWebApplication.MigrateDatabaseHelper(SPContentDatabase database, SPCommonMigrateUserParameters commonParams, Dictionary`2 processedOldLogins)
    at Microsoft.SharePoint.Administration.SPWebApplication.MigrateUsers(IMigrateUserCallback callback)
    at MigrateUsers(Object , Object[] )
    at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[] originalArguments)
    at System.Management.Automation.DotNetAdapter.MethodInvokeDotNet(String methodName, Object target, MethodInformation[] methodInformation, Object[] arguments)
    at System.Management.Automation.Adapter.BaseMethodInvoke(PSMethod method, Object[] arguments)
    at System.Management.Automation.ParserOps.CallMethod(Token token, Object target, String methodName, Object[] paramArray, Boolean callStatic, Object valueToSet)
    at System.Management.Automation.MethodCallNode.InvokeMethod(Object target, Object[] arguments, Object value)
    at System.Management.Automation.MethodCallNode.Execute(Array input, Pipe outputPipe, ExecutionContext context)
    at System.Management.Automation.ParseTreeNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
    at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
    at System.Management.Automation.StatementListNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
    at System.Management.Automation.ParseTreeNode.Execute(Array input, Pipe outputPipe, ExecutionContext context)
    at System.Management.Automation.ScriptCommandProcessor.ExecuteWithCatch(ParseTreeNode ptn, Array inputToProcess)
    at System.Management.Automation.ScriptCommandProcessor.RunClause(ParseTreeNode clause, Object dollarUnderbar, Object inputToProcess)
    at System.Management.Automation.CommandProcessorBase.DoComplete()
    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
    at System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()
    at System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()
    at System.Management.Automation.Runspaces.PipelineThread.WorkerProc()
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ThreadHelper.ThreadStart()

    I’ll trim out the awful details of sitting on the phone with Microsoft technical support, and jump right to the fix.

    It turned out that when this SharePoint farm was upgraded from 2007 to 2010, there was a residual site collection in one of the content database.  Further, it so happened that this site collection had the same name and url as a sub site in another site collection.

    It appeared that as the MigrateUsers method was iterating through the site collections, it would follow the url to open the site collection and retrieve the users in order to convert them.  In this case, however, the url led not to a site collection, but a sub site, and thus the ‘Object reference not set to an instance of an object.’ error occurred.

    After confirming that the residual site collection was unused and contained no content, I (nervously) deleted it in Central Administration.

    I then re-ran the MigrateUsers() method, and it successfully converted the users for all site collections, and users were able to authenticate properly to the sites.

    I recognize this is an unusual situation due to the particular data in this installation.  But having found very little information about any such case, I wanted to share my experience.

  • Locked file in SharePoint Configuration Cache

    This post will deal with all of the following fantastic error messages:

    Access to the path C:\ProgramData\Microsoft\SharePoint\Config\<guid>\<guid>.xml is denied.

    File system cache monitor encountered error, flushing in memory cache: System.IO.InternalBufferOverflowException: Too many changes at once in directory:C:\ProgramData\Microsoft\SharePoint\Config\

    It all began for me when attempting to do a routine clearing of the SharePoint configuration cache in the manner that is well documented by Microsoft and various bloggers.  All went well, so I thought, but there were two oddities left behind:

    1. the cache.ini file never updated with a new value after resetting it to 1
    2. there was an odd file with an xml.tmp extension on it that would never go away

    I tried repeating the steps to clear the cache, but every time, those two results would occur.  Meanwhile, my ULS logs were getting flooded with the 888k File system cache monitor encountered error entries, and the CPU utilization on that server would spike to 100% about every 5 minutes.

    Every other article discussing the configuration cache suggests that just clearing it will resolve these issues.  But not for me.

    The next clue that something was not right was when I tried to issue a Powershell command to update a Web Application object.  There was a nervous pause, then the ‘Access denied’ error would be displayed.  Interestingly, the file that was indicated in the error had the same Guid filename (but without the .tmp extension) as the file that wouldn’t go away.

    Thinking I could just delete this file manually, I opened Windows explorer and tried to delete it.  Nope, Access Denied.

    I then looked a the properties of the file, and was told ‘You don’t have permissions to view the security information.’  What?  I’m an administrator.  Don’t tell me I don’t have permissions.

    Googling…googling….googling.

    After finally going down the ‘how to delete a locked file’ route, I came to this post on Serverfault, which introduced me to Lockhunter.

    Download, install, browse to C:\ProgramData\Microsoft\SharePoint\Config\GUID.

    Lockhunter showed about a half-dozen locked files, including the one I was getting the Access Denied error on.  The owner of the file?  miiserver.exe

    This process is none other than the Microsoft Forefront Identity Manager service used by the SharePoint User Profile Synchronization feature.

    After stopping the SharePoint Timer service and the SharePoint Administration service, I opened Central Admin, browsed to Services on server, found the User Profile Synchronization Service entry, and clicked Stop!

    Ever so slowly the service stopped, and when I refreshed Lockhunter, the entry for miiserver.exe was gone.

    A quick browse back to the Config directory showed that the xml.tmp file was gone, and the value in the cache.ini file had been restored back up to a value that wasn’t 1.

    I definitely hope this helps others who find themselves in similar situations, at least offering a process to find out the culprit.