Skip Ribbon Commands
Skip to main content

Quick Launch

Home
Lessons from the field by SharePoint's Premier Field Engineers
April 23
Customizing the MySiteCleanup job

One issue that always comes up at my customers is the MySiteCleanup Job. They are not satisfied with the default implementation that SharePoint provides, and they want to change that way it behaves. Some feature requests for the job that I ran into so far with my various customers:

 

-        No “grace” period till a user (and later his MySite!!!) is deleted after missing from an Import
-        Violation of data privacy by granting MySite access to the manager
-        Modification of the Emails send out (The My Site of "User" is scheduled for deletion. As their manager you are now the temporary owner of their site[…])
-        Splitting requests for the job tasks, so each step can be toggled on/off by itself (usually caused by the manager issue)
-        No (supported) way to “stop” a site deletion once it was started
 
While most of these requests are “nice to have”, the manager issue is usually the one that kills the MySiteCleanup Job. Under German (and also EU) data protection laws, granting a manager access to his employees private files is a big no, and letting the Betriebsrat (Workers council) know about it is a sure way to turn it off. (It’s a sure way to turn almost any collaboration feature in SharePoint off, I did mention we have tight data protection laws?)
 
There is a way to completely modify the way this job is behaving. While this topic is coming up again and again (at least for me), there are very few resources that actually talk about how to modify this behavior but first let’s have a small review of the default implementation. Chun Liu’s Blog  published a small flowchart on what exactly it does, or check Spence’s blog for a bit more details about it.
 
1.      Cleanup user profiles
a.      Set the owner to the manager
b.      Inform the manager that he is owner
c.      Schedule site for deletion
d.      Delete Userprofile
2.      Cleanup MySites
a.      Send a reminder email after 11 days
b.      Delete the site after 14 days
 
One important thing to mention is that this job is the only place where SharePoint will remove an old user profile (there is no longer a “3-miss and you are out” policy in the UPA import). So turning this job “off” will leave you with all old user profiles in your UPA.
 
What is interesting is that the steps in the 1st section can be modified. Basically the steps 1.a to 1.c are implemented in the Class MySiteProfileHandler and the profile is actually deleted if the method PreProfileDeleted() returns true. This is also the class that can be replaced by a custom implementation. To replace this class, you need to create your own version, which implements the IProfileEventInterface.
 
One thing that is a bit awkward about this implementation is that the class “only” implements 1.a -1.c. So, even if you replace it, you will still have the old implementation of the 2nd part of the job “active”. But since you are not able to schedule a site for deletion in your custom code, the 2nd part of the job does actually nothing at all. This means you also have to make sure you handle the MySite deletion properly. Since your code won’t be revisited after you gave your consent to delete the user, you need to make sure you implement an alternative workflow. 3 possible solution would be to either postpone the deletion of the user by X Days (Until you handled the MySite yourself), or create a small site workflow, attached to the MySite, that will cause the MySite to “self-destruct” after the given time (This wasn’t possible when the default timer job was implemented, but you have the option now), or backup and delete it right away (This would allow for a different retention of the MySite backups)
 
So once you have created the new class and put it into the GAC, the one step that is missing in order to use it in SharePoint is to register your custom implementation. To do this you have to fall back to a stsadm. You need to register the new class to running stsadm -o profiledeletehandler -type <full assembly path>  http://technet.microsoft.com/en-us/library/cc263114(v=office.12).aspx  . This will store the type you entered in an internal (sorry, calling internal methods is also unsupported) property ProfileDeleteEventHandler of the MySiteCleanUpJob Instance.
After that is done, SharePoint will apply your logic to the MySiteCleanup job, and you are set.
 
The are some drawbacks that you have to consider:
-        Needs to be registered via STSADM
-        Needs an assembly deployed into the GAC
-        Not very transparent for a new Admin
-        Unable to access the internal MySiteDeletion “Workflow” from my custom code – Need to reinvent the wheel
 
The option I would have loved the most, is the ability to configure how this process behaves right out of the box, but this is as close as we can get. Finding this option kind of surprised me, since there are very few places in SharePoint that use Interfaces (I love unit tests)
 
 
I hope you will find this information usefull. If there are any questions, feel free to ping me.

 

 

 

 

 

March 14
Speaking at The SharePoint Evolution Conference

Hi all,

In just over a month, what is set out to be THE SharePoint conference of the year, will be taking place in London. The SharePoint Evolution Conference will be happening April 15-17th 2013, at the Queen Elizabeth II Conference Centre, London.
 
I’ve attended this conference numerous times in the past, and it is fair to say that this conference is unique in a number of ways. Not only is there an agenda packed with quality, diverse and targeted sessions, the speaker line-up is truly outstanding with a raft of globally recognised experts from the MVP, MCM and MCA communities, not to mention presence from the Microsoft SharePoint Product Group.
 
With that in mind, I’m honoured to be presenting at the conference this year. Chris Whitehead and I will be presenting a session entitled “SharePoint 2013 Backup and Recovery with DPM 2012“. This session will be targeted at IT Pros, Architects and Administrators, who want to find out more about protecting SharePoint 2013 with Data Protection Manager 2012.
 

The focus of this session will be on DPM 2012 and how it complements the out of the box backup and recovery tools to provide simple, fast, and automated recovery of SharePoint data.

If you’re attending the conference please come over and say Hi, it would be great to meet as many of you as possible!
 
Finally, this is the last blog post I’ll be publishing here, from April I’ll be starting a new adventure outside of Microsoft, and you can follow me here http://www.samhassani.com. The PFE team will of course continue to post great content here.
 
Hope to see you at the conference!
 
Cheers,
Sam

 

February 15
Community Sites - Where are my analytics reports!

Community Sites are a new type of site introduced in SharePoint 2013, if you are unfamiliar the following article has some background information on their purpose and functionality - http://technet.microsoft.com/en-us/library/jj219805(v=office.15)

I was playing around with a Community Site the other day and noticed something very strange, for some reason in Site Settings it includes links to the SharePoint 2010 Web Analytics reports. As you may know Web Analytics has been removed from SharePoint 2013 and its functionality has been replaced by the Analytics Processing component provided by Search - http://technet.microsoft.com/en-gb/library/ff607742.aspx#section1.
 
Below is a screenshot of how this appeared:
 
WebAnalyticsLinks.PNG

As Web Analytics isn’t available in SharePoint 2013 neither of these reports work, in addition to this links for the SharePoint 2013 equivalent analytics reports are missing – Popularity and Search Reports & Popularity Trends. What should appear is the following (taken from a standard “Team Site”).

Community Site.PNGCommunity Site 2.PNG

I did some digging around and found that the reason for this is that the Site Collection “Reporting” feature isn’t activated for Community Sites by default, activating this feature removes the links to the legacy SharePoint 2010 Web Analytics Reports and adds links to the new SharePoint 2013 Analytics reports. Not sure exactly why this feature isn’t automatically activated!
 
ReportingFeature.PNG
If you do need to access the reports for Community Sites it is simple enough to activate the feature ot put together a PowerShell script to automate the activation of this feature across all Community Sites. To prevent this from occurring in the future you could staple the “Reporting” feature to the Community Site template, this will ensure that all new Community Sites have the “Reporting” feature activated automatically.
 
Brendan Griffin

 

February 13
We have been moonlighting......

​A number of the SharePoint PFE team have recently contributed to the Premier Field Engineering WW Blog - http://blogs.technet.com/b/mspfe/ be sure to check out these great posts!

Planning Deployment of Farm Solutions for SharePoint 2013 - http://blogs.technet.com/b/mspfe/archive/2013/02/04/planning-deployment-of-farm-solutions-for-sharepoint-2013.aspx

How To Customize SharePoint 2013 Search Results Using Query Rules and Result Sources - http://blogs.technet.com/b/mspfe/archive/2013/02/01/how-query-rules-and-result-sources-can-be-used-to-customize-search-results.aspx

How To Configure SharePoint 2013 On-Premise Deployments for Apps -http://blogs.technet.com/b/mspfe/archive/2013/01/31/configuring-sharepoint-on-premise-deployments-for-apps.aspx

Understanding SharePoint Apps as an IT Pro - http://blogs.technet.com/b/mspfe/archive/2013/01/31/understanding-sharepoint-apps-as-an-it-pro.aspx

The Top 30 New Reasons to Use SharePoint Server 2013 for Public-Facing Internet Sites - http://blogs.technet.com/b/mspfe/archive/2013/01/29/public-facing-internet-sites-based-on-sharepoint-server-2013.aspx

 

Brendan Griffin

 

February 07
Programmatically modifying the SharePoint web.config to add the defaultProxy settings

In my ealier post, I had mentioned that I was a reluctant blogger, which is still the case.  Howerver, it make sense to blog if I am going to save time for someone else.

Modiying the web.config is not something new, there are blogs which covers a similar topic.  My intention is to share the complete process and the code that works.  As of now, I am only going to provide instructions and the screenshots, but as soon as I find some free time, I will upload the entire project.  As the current project is part of the bigger project.
 
My intention is to automate the defaultProxy settings in the web.config. 
 
Remember SharePoint farm can have many servers.  Making a manual entry on each server is not a wise choice.  Therefore, deploying via  feature will come in handy for today and for future configurations especially for a Disaster recovery scenario.  Even when you add a new SharePoint server to the farm, these configurations are automatically applied.
 
Before changing the Web.config programmatically, the web.config proxy settings will look as shown below
 
<system.net>
    <defaultProxy />
<system.net>
 
After changing the web.config programmatically
<system.net>
    <defaultProxy>
      <proxy proxyaddress="
http://proxy.godwin.net:8080" bypassonlocal="true" />
      <bypasslist>
        <add address="[a-z0-9\.]+\.godwin\.com" />
        <add address="sharepoint\.godwin\.net" />
      </bypasslist>
    </defaultProxy>
 
<system.net>
 
Please note – the above url is just an example.

 

1)      First create a visual studio project – using Empty SharePoint Project template

 

2)      Within the Empty SharePoint Project, add a new Feature with Web Application scope.  Obviously name the feature using a friendly and appropriate name.
 
3)      Right click on the newly created Feature node and add an Eventreceiver to the feature
 
So when the solution is deployed and when this feature is activated, I want the web.config changes to be applied.  Suppose if I have to deactivate and retract the solution, then I want the changes to be reverted. 
 
To achieve this, I will have to write the code that makes the web.config changes or additions within FeactureActivated and I should write the code that reverts the web.config changes in the FeatureDeActivating event as shown below.
 
The entire code that you need to make the proxy change in the web.config is shown below.
 
I am using SPWebConfigModification class and xpath to safely add and remove modification from the Web Application web.config file.  SPWebConfigModification has many benefits over other APIs that will allow you to modify the web.cofig entries.
 
With SPWPWebConfigModification every change has an owner.  In the above code, I have assigned the owner as „SharePoint.ApplyProxyConfiguration, which is the project assembly name.   Because every change has an owner, based on the owner value, it is easy to revert the change that is made by a specific assembly or feature.    Also the SPWebApplication class has a SPWebConfigModifications collection property that contains all the modifications (SPWebConfigModification objects) made to this web application’s web.config file.
 
The output of the following Xpath is shown in the second screenshot below
 
 
The above Xpath adds the <proxy ........../> line as shown below.
 
SPWebConfigModification includes the following properties
 
·        Name  -  Gets or sets the name of the attribute or section node that should be set.
 
In the above example Proxy is the new node. To add an a new node or to modify an existing node under the path which is the next property, you can simiply write 
  
 
·        Path  -  Gets or sets the XPath expression that is used to locate the node that is being operated on.   
In the above example, the original path in the web.config is 
<configuration>
     <system.net>
            <defaultProxy />
     </system.net>
</configuration>
 
Syntax
“configuration/configSections/sectionGroup[@name=’sectionname’]”
 
Which is simply written in the XPath as     - 
 
·        Owner -    Gets or sets the owner of the web.config modification.  This will have to be the unique name.   In the above example, I am using the assembly name.  However, you can also consider either Feature name or feature id.
 
·        Sequence -  Gets or sets the sequence number of the modification.
 
·        Type -  Gets or sets the type of modification that is implied by the class. The following types are supported
 
EnsureChildNode - Specifies that the web.config modification must ensure the existence of a child node of the node to which the XPath expression points.
 
EnsureAttribute - Specifies that the web.config modification must ensure that there is a value for a particular attribute.
 
EnsureSection - Ensures a singleton node. This node is only written once, even if multiple entities register multiple instances of EnsureSection to ensure the existence of a section.  Please do use EnsureSection, unless you do not want to remove this section.   Nodes created with EnsureSection cannot be removed.
 
·        UpgradePersistedProperties -  Gets the collection of field names and values for fields that were deleted or changed.
 
·        Value -  Gets or sets the value of the item to set. In the above example it is
 
 
Suppose if you are writing the feature to simply change an existing attribute in the web.config.  for example, you want to change from  <customErrors mode="On" /> to  <customErrors mode="Off" />
 
Then the xPath code should look as shown below
 
 gtdev8.png
I hope the above explanation helps.  Very soon, I will try to include the entire project part of the blog post. 
 
 
 
 
 
 
 
 

 

February 07
Limiting SharePoint Designer or Office client functionalities using Group Policy

One of the question, that I often come across from my customers, how do I restrict SharePoint Designer or how do I restrict certain UI actions in SharePoint designer.   Virtually every office client UI can be disabled/hidden using Domain or Local Group Policy. 

 
To be able to control the Office client applications using group policy, you will have to download the Office administrative template files
 
 
Depending on the 32 or 64 bit version of the office, download & install the appropriate policy template file.
 
Once you install, you will notice the following folders.  The Office 2010GroupPolicyAndOCTSettings.xls file contains the details about all the policy settings for the office applications.
 
The ADM folder contains the policy template files for the relevant office clients in various languages.   ADM Administrative Templates facilitate the management of registry-based policy. An ADM file is used to describe both the user interface presented to the Group Policy administrator and the registry keys that should be updated on the target machines.
 
 
The following screenshot shows the default nodes under Administrative Templates.   The default templates does not include Office client specific policy configuration.  
 
To add the Office client administrative policy template, from the Group Policy Editor -> User Configuration -> Administrative Templates -> Add/Remove Templates..   as shown below.  Select the appropriate language specific policy template.  In this example, I will be choosing SPD14.adm.
 
 
Once you add the policy template for SharePoint designer, you will notice the additional nodes that are highlighted in the screenshot below.  
 
 4.png


By double clicking the Disable commands from the right pane.  From the Disable Commands dialog, I can customize the SharePoint Designer UI and the UI options that I want to disable.   Just for this demo, I have selected all the options in the Disable Commands window.
 
 5.png
 
The outcome of the group policy restriction is shown below
 
 6.png
 
The predefined policy only allows restricts certain UI actions.  However, using the custom policy - you can disable more UI options using the Office client command bar ID for the UI action.   For all Office client applications except SharePoint Designer, these ids are well documented.
 
You can download the Office2010ControlIDs.exe, from Microsoft website, which includes the control ids and the numeric values that you need for the policy configuration.
 
 
For SharePoint none of these ids are documented or maybe I was unable to find it.  However, for this demo, I am going to use a Command Bar ID which is consistent across most office client applications.  Command Bar Id 18152 refers to Change Product Key section.  Using this id, I can hide the Change Product Key / Production Activation section from the SharePoint Designer or Office Client UI as shown in the second screenshot below.
 
7.png

 
 
This screenshot shows before disabling the Product Activation area
 
 8.png

 
After disabling the Product Activation area
 
 9.png 
If you were looking for instruction to restrict SharePoint designer or Office client applications using group policy then I hope this is useful to you.
 
I am still searching for the SharePoint Designer specific Command Bar ids.  If I was able to find, then I will update this article asap.

Hopefully in my next Post I will update the Command Bar Ids, if I am able to find it.

January 09
Copying a list using Export/Import-SPWeb and SharePoint Designer

 

Sometimes it’s the simple solutions that are the best. I was recently asked if Export/Import-SPWeb could be used to create a copy of a list within a site in SharePoint 2010, the reason for doing this was to take one large list and split it into two smaller lists - easy I thought!
 
However taking a look at the syntax for Import-SPWeb - http://technet.microsoft.com/en-us/library/ff607613(v=office.14) it’s not actually possible to rename a list on import. By default if a list exists at the same URL it will be overwritten/merged on import depending on settings used with the UpdateVersions parameter.
 
The solution I found to this was to use SharePoint Designer to change the URL for the original list after Export-SPWeb was performed, for example I changed http://intranet/lists/MyList to http://intranet/lists/MyListOld. When the restore is performed the list will be restored to http://intranet/lists/MyList, resulting in two duplicate lists within the site.
 
·        Original list that was backed up – http://intranet/lists/MyListOld
·        Restored list – http://intranet/lists/MyList
 
The list names/URLs can then be updated as required using SharePoint Designer. I’m sure that this can also probably be done using PowerShell J
 
Below are the high level steps:
 
Steps
·        Export a list using Export-SPWeb
·        Connect to the Site hosting the list using SharePoint Designer
·        Select “All Files” then “Lists”
·        Select the list in question and click “Rename”
·        Provide a new name for the existing list – this will also update the URL
·        The URL and display name of the list are now changed, for some reason the list name isn’t updated in the left hand navigation, to remedy this go into “List Settings” and select “Title, description and navigation” all you need to do is open this and click Save, the left hand navigation will now be updated
·        Import the list exported in Step 1, this should restore the list into its original URL (as it was prior to step 2 being performed).
·        Rename the two lists if required using SharePoint Designer
 
Brendan Griffin

 

November 05
​​Orphaned sites revisited in SP2010

I ran into an  issue at one of my customers today. Some users called and complained that most “current” content was missing. This could happen if an orphaned site is “surfacing” due to a contentDB switch.

 

Since we had a maintenance weekend I was quite fast in finding the root cause of the issue. The farm had a total of 3 “real” orphaned sites, and since murphy is a good friend of mine, all managed to get switched.

 

There is a lot of information on what an orphaned site is, and how to get rid of them, but most of this information originates from the MOSS area. For example here are some links explaining that explain it:
That article has a “few issues”, one of them is a direct SQL query against your SharePoint DB’s (And it only works for a single Database instance)
 
Detecting orphaned sites has gotten much easier in SP2010. You now have several tools at your disposal, so that you don’t have to rely on SQL queries anymore. I’ll try to list all way I know of to find those sites.
 
1.  Stsadm -o  enumallwebs > output.txt (MOSS/SP2010)
Now check for this string in the output.txt file: inSitemap=”false”
This will allow you to find all sites in all contentDBs that have no entry in the config DB.
 
2.  Test-SPContentdatabase (SP2010)

This command will also output all site orphans, if it is run against a connected contentDB. It will not modify anything in the DB, but it can generate some load against the DB.
 
3.  Health rule: Content databases contain orphaned items (SharePoint Foundation 2010) (SP2010)

This  health rule will also detect the presence of site orphans in your farm, but you should NOT use it to clean up the issue, since it will just delete all orphaned sites, giving you no chance to check what’s in them.
 
4.  Stsadm -o preupgradecheck (MOSS only)

This also contains a rule that will help you to detect site orphans. The rule will flag as an “Error”
 
 
One of the pitfalls when working with orphaned sites is that you have 2 copies, and you need to keep both. Usually users manage to upload some files before noticing it and requesting that you restore the original site. So it is mandatory that you also backup the “old” site, and make it available to the user after you restore the new site for them, so they can fetch the documents from the “old” site.
Most sources in the Internet talk about detaching and attaching contentDBs in order to switch the sites again. This can be an issue if you have many users accessing your farm, and you don’t want to work overtime that evening just to switch them out.
So in Sp2010 Microsoft introduced a small Method that can help you out here. The SPContentDatabase  object has a handy method that will allow you to register all sites in the configDB again. The method I am talking about has a nice descriptive name: RefreshSitesInConfigurationDatabase
The main advantage of this command is that it can be used without any service interruptions for other users. So there won’t be a need for sending out emails or waiting for a maintenance window.
So in order to surface the orphaned version of the site, you need to do the following:
  • Delete the current site
  • Retrieve the contentDB with the orphaned site inside
  • $db.RefreshSitesInConfigurationDatabase()
In order to remove an orphaned site, you can use the stsadm command deletesite. The force parameter allows you to delete sites that are orphaned. The parameter was introduced in MOSS SP2.
  • Stsadm -o deletesite -force -siteid <site ID> -databasename <database name>  -databaseserver <database server name>
A last note… Before you do any upgrades, you should always check if some orphaned sites managed to creep into your farm. It is much easier to eliminate them early, and also it will make your upgrade process run smoothly.
 
I hope this helps you guys out a bit.
Heiko Hatzfeld
SharePoint 2010 MCM
 

 

October 02
SharePoint 2013 (Technical Preview) MySite Upgrade and Profile Photos

I recently assisted a customer perform a test upgrade of their SharePoint 2010 environment to SharePoint 2013 Technical Preview; one of the issues that we experienced related to the user profile photo that is displayed in MySites.

To provide some background, for the test migration different URLs were used for each of the Web Applications that was upgraded (for obvious reasons!). For example the existing SharePoint 2010 MySite Web Application used the URL http://mysite, for the test migration to SharePoint 2013 Technical Preview http://mysite2013 was used.
 
Post upgrade everything worked apart from a strange issue with users profile photos, for some reason these were still rendering from the SharePoint 2010 version of the MySite, right clicking a user’s Profile Photo in their MySite and selecting properties confirmed this as the following URL was being used – http://mysite/User%20Photos/Profile%20Pictures/user_LThumb.jpg, this should have been rendering from the upgraded SharePoint 2013 MySite URL, which is – http://mysite2013/User%20Photos/Profile%20Pictures/user_LThumb.jpg.
 
The reason for this behaviour is that the URL for a user’s Profile Photo is held within their SharePoint User Profile and this had not been updated when the User Profile Service Application had been upgraded and configured with the new SharePoint 2013 MySite URL – http://mysite2013
 
This issue was easy enough to rectify using some new parameters that are included in the Update-SPProfilePhotoStore cmdlet - http://technet.microsoft.com/en-us/library/ff607547(v=office.15).aspx. The parameters OldBaseUri and NewBaseUri can be used to update users profile with the new MySite URL for their profile photo.
 
In this specific case running the following command rectified the issue:
 
Update-SPProfilePhotoStore -MySiteHostLocation http://mysite2013  -OldBaseUri http://mysite -NewBaseUri http://mysite2013

 

Brendan Griffin

July 20
SharePoint 2013 Installation error – Cannot connect to database master at SQL Server

 

 
 
SharePoint 2013 is still at the early days.  I know many of you will be looking at installing SharePoint 2013 in the coming days.  
 
I am a relucatant blogger , but hopefully my short and sweet resolution may save you sometime.
 
When you run the SharePoint 2013 configuration wizard for the first time, at the SharePoint Configuration Database settings, once you enter the appropriate Database server, database name, username and password, you may come across the error that is shown below
 
“Cannot connect to database master at SQL Server at <ServerName>.  The database might not exist, or the current user does not have permission to connect to it.”

SharePointConfig1.png
Cause
This is because TCP/IP protocal for SQL Server is disabled by default as shown below in the screenshot.
 
SQLConfig1.png




Resolution
Open SQL Server Configuration Manager from the SQL Server
Expand to the SQL Server Network Configuration node
Click the Protocols for MSSQL Server, from the right pane, select TCP/IP, right click and Enable the protocol as shown below
SQLConfig2.png


Note: Enabling any protocol requires a restarting SQL Server services.
 
I hope the above instruction helps you.  Good luck with SharePoint 2013 venture.
 
Godwin Tenzing
Microsoft PFE - UK

 

1 - 10Next