SharePoint Experts, Information Architects, Expert Witness

We provide consulting in a broad array of business and technology from architecture to design to deployment of global systems with a focus on surfacing data in the enterprise. Specialists in Microsoft, we are a premier provider of SharePoint Expertise (including 2016 and Office 365). We also provide Expert Witness/Legal Expert in eDiscovery, source discovery, patent infringement, piracy and more! We also have established SICG DLDS s.a. - our counterpart in Costa Rica that specializes in water systems (http://www.crwatersolutions.com) - Contact me direct: david_sterling@sterling-consulting.com or call 704-873-8846 x704.

Search This Blog

Saturday, December 17, 2016

Creating Site Templates in SharePoint 2016 and SharePoint Online (including Publishing sites!)

Like many of you, I was dismayed to find that SharePoint Online can't be used to create templates and have always not liked being able to save a Publishing Site as a template.

In SPO, Microsoft says that since they automatically turn on Publishing that it cannot be done and that turning off publishing (which has to be done for the entire site collection) won't fix it because there are other features that are enabled. If you test it out, you'll find this to be the case.

In SP on premise, Microsoft disables the option to save publishing sites, however use either Workaround below and it does!

WARNING 1: If you try to save a site with content, most commonly a publishing site, it will FAIL if there is too much content. Best to save with a near-empty site!

WARNING 2: When you save a publishing site as a template using Metadata Navigation, the Navigation will be screwed up when you create a site from the template. It has to be reset to fix it through Site Settings > Navigation.

So - two ways to set the property to enable saving as a template:

Workaround 1:
http://blogs.msdn.microsoft.com/how24/2013/06/13/save-sharepoint-2013-publishing-site-as-a-template/

* THIS works in the on premise version.

Another way to get around it is through SharePoint Designer:

Workaround 2:
http://community.bamboosolutions.com/blogs/sharepoint-2013/archive/2014/05/12/how-to-enable-save-site-as-template-in-sharepoint-2013-using-sharepoint-designer.aspx

* THIS works in the online version.

ANOTHER way to set the property in SharePoint Online is through the SharePoint Online Management Shell (setting the Property Bag):

$SiteUrl = "https://somesite.sharepoint.com/"
$context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$sUserName = "someone@somedom.com"
# Prompt for Password:
$sPassword = Read-Host -Prompt "Enter your password: " -AsSecureString
# Set the Site URL:
$spoCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($sUsername, $sPassword) 
$context.Credentials = $spoCredentials
$web = $context.Site.RootWeb
$web.AllProperties["SaveSiteAsTemplateEnabled"] = "true"
$web.Update()

* This doesn't always work on Publishing Sites so I'd suggest using the Designer method.

However, I found that these solutions don't always work, particularly in SharePoint Online. There are hidden features (i.e. can't be turned on through the UI) that prevent the template from working in other site collections. I did however finally find a way to get it to work using the SharePoint Online Management Shell. By running the following script on the site collection, it enables all of the features you need to get the templates to work.

Once this script is run, you can go to the site you want to make a template of and simply alter the URL - so:

https://somesite.sharepoint.com/sitename

Enter:

https://somesite.sharepoint.com/sitename/_layouts/15/savetmpl.aspx

Kudos to the following post:
https://gallery.technet.microsoft.com/office/How-to-enable-a-SharePoint-5bb614c7

Here's the script - simply set the account name and the URL path to the site collection accordingly.

===========================================================
NOTE: You have to get a copy of the DLL's necessary for the following lines:

Add-Type -Path "C:\temp\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\temp\Microsoft.SharePoint.Client.Runtime.dll"

If you have an on-premise copy, you get get them from the ISAPI folder:
c:\program files\common files\microsoft shared\web server extensions\15\ISAPI

OR download them from here:

https://www.microsoft.com/en-us/download/details.aspx?id=35585
===========================================================

To use a template, you have to enable these features at the TOP LEVEL site collection; that is, say you create a template in Collection 1, you have to enable these features to use the template in Collection 2. 

$host.Runspace.ThreadOptions = "ReuseThread"
#Definition of the function that allows to enable a SPO Feature
function Enable-SPOFeature
{
param ($sSiteColUrl,$sUserName,$sPassword,$sFeatureGuid) 
try
{
#Adding the Client OM Assemblies 
Add-Type -Path "C:\temp\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\temp\Microsoft.SharePoint.Client.Runtime.dll"
#SPO Client Object Model Context 
$spoCtx = New-Object Microsoft.SharePoint.Client.ClientContext($sSiteColUrl) 
$spoCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($sUsername, $sPassword) 
$spoCtx.Credentials = $spoCredentials
Write-Host "----------------------------------------------------------------------------" -foregroundcolor Green
Write-Host "Enabling the Feature with GUID $sFeatureGuid !!" -ForegroundColor Green
Write-Host "----------------------------------------------------------------------------" -foregroundcolor Green
$guiFeatureGuid = [System.Guid] $sFeatureGuid
$spoSite=$spoCtx.site 
$spoSite.Features.Add($sFeatureGuid, $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None) 
$spoCtx.ExecuteQuery() 
$spoCtx.Dispose() 
}
catch [System.Exception]
{
write-host -f red $_.Exception.ToString() 
}
}

# Required Parameters

# Modify Username above with your administrator credentials:
$sUserName = "someone@somedom.com"

# Prompt for Password:
$sPassword = Read-Host -Prompt "Enter your password: " -AsSecureString


$sSiteColUrl = "https://somesite.sharepoint.com"
# Modify feature ID as needed (this one is MobileExcelWebAccess needed to use templates):
$sFeatureGuid= "e995e28b-9ba8-4668-9933-cf5c146d7a9f"
# Enable it (MobileExcelWebAccess): 
Enable-SPOFeature -sSiteColUrl $sSiteColUrl -sUserName $sUserName -sPassword $sPassword -sFeatureGuid $sFeatureGuid 
# Library and Folder Based Retention - LocationBasedPolicy Feature
$sFeatureGuid= "063c26fa-3ccc-4180-8a84-b6f98e991df3"
# Enable it (LocationBasedPolicy): 
Enable-SPOFeature -sSiteColUrl $sSiteColUrl -sUserName $sUserName -sPassword $sPassword -sFeatureGuid $sFeatureGuid 
# Site Policy - ProjectBasedPolicy Feature
$sFeatureGuid= "2fcd5f8a-26b7-4a6a-9755-918566dba90a"
# Enable it (ProjectBasedPolicy): 
Enable-SPOFeature -sSiteColUrl $sSiteColUrl -sUserName $sUserName -sPassword $sPassword -sFeatureGuid $sFeatureGuid 
# Three-state workflow - IssueTrackingWorkflow Feature:
$sFeatureGuid= "fde5d850-671e-4143-950a-87b473922dc7"
# Enable it (IssueTrackingWorkflow): 
Enable-SPOFeature -sSiteColUrl $sSiteColUrl -sUserName $sUserName -sPassword $sPassword -sFeatureGuid $sFeatureGuid 
# SitePageResources Feature
$sFeatureGuid= "ff77ac56-88d0-4147-b865-e84f5f03fc42"
# Enable it (SitePageResources): 
Enable-SPOFeature -sSiteColUrl $sSiteColUrl -sUserName $sUserName -sPassword $sPassword -sFeatureGuid $sFeatureGuid 

Opening Documents in a New Window (SharePoint Online 2013/2016)

Ever wanted SharePoint Online Documents to open in a new window?

As many have needed to, some want to be able to open documents from SharePoint Online in a new window instead of the same window - useful when you have to edit a number of documents at the same time.

I looked for several solutions - most didn't work however, I found one that did after making a few tweaks.

This minor modification enables you to set it on a library by library basis or you can save the library as a template once the script is put in a set place. Once you add it to the library view page, it applies TO ALL Views in the library.

NOTE: This does make a change to the way a library works - when you add a content editor web part to a library view, it HIDES the Files/Library tabs! Thanks for the bug but there is a work around.

To get started, here's the script - taken & modified from
http://sharepoint.stackexchange.com/questions/116769/opening-a-document-in-a-sharepoint-2013-document-library-in-a-new-tab-using-cod - the original script from there didn't work for me so I modified it for Office 365/SharePoint Online:

<script type="text/javascript">
// OPEN DOCUMENTS IN NEW WINDOW SCRIPT
//
// Create a namespace for the functions so we don't collide with anything else:
//
var customFunctions = customFunctions || {};
//
// Create a function for customizing the Field Rendering of our display fields:
//
customFunctions.CustomizeOpenFieldInNewTab = function () {
    var fieldJsLinkOverride = {};
    fieldJsLinkOverride.Templates = {};

    fieldJsLinkOverride.Templates.Fields =
    {
        // Make sure the Your field view gets hooked up to the method defined below
        'LinkFilename': { 'View': customFunctions.GetDocumentsField },
    };
    //
    // Register the rendering template
    //   SPClientTemplates.TemplateManager.RegisterTemplateOverrides(fieldJsLinkOverride);
};
//
// Create a function for setting the proper URL to open in new window:
//
customFunctions.GetDocumentsField = function (ctx) {
    var myColumn = ctx.CurrentItem.ServerRedirectedEmbedUrl;
    var myFileName = ctx.CurrentItem.FileLeafRef;
    var editFileLink = myColumn.replace("interactivepreview", "default");
    var myIndex = myFileName.lastIndexOf(".");
    myFileName = myFileName.substring(0, myIndex);
    //
    // Change the default URL to use Open in New Window:
    //
    if (myColumn) {
        return "<a href='" + editFileLink + "' target='_blank'>" + myFileName + "</a>";
    }
    return ctx.CurrentItem.ServerRedirectedEmbedUrl;
};
//
// Call the function:
//
customFunctions.CustomizeOpenFieldInNewTab();
</script>

First, save this script to a text file - i.e. OpenInNewWindowForView.txt.

Step 1 - Create a new document library that everyone has access to - I like to call it 'Scripts' so I know what it is for. Everyone must have read access to this or it will 'break' the library view.

Step 2 - Upload the OpenInNewWindowForView.txt file into the library; once loaded, click on the file to open it - it will open in the browser window to display the text. Copy and save the URL from the browser.

Step 3 - Open the library you want to modify and select the "All Documents" view (actually modifying any view will modify it for all views).

Step 4 - Edit the page - add a Content Editor web part to the top of the page (above the view of documents).

Step 5 - Edit the Content Editor web part and in the "Content Link" of the properties, paste in the URL path you saved in Step 2 and click OK to save.

Step 6 - Stop Editing the page and you are done!

Once the script has been added, if desired, you can save the library as a template but be sure that the script is accessible from any location otherwise it won't work!

NOTE: CHANGE IN BEHAVIOR! Once the Content Editor web part has been added, it 'breaks' the library in that the "Files" and "Library" tab disappear (!). This is easily overcome however:

1) To get to the settings, you can use the Site Contents Page - mouse over the library and click the ellipsis (...) to get to Settings.

2) Simply select any document or folder in the list and the "Files" and "Library" tabs re-appear.

Tuesday, November 22, 2016

SharePoint Online Library Template Error The SPListItem being updated was not retrieved with all taxonomy fields

So you have multiple site collections in SharePoint Online and decide you want to use a List or Library template that happens to have a Taxonomy (metadata) Column that you want to add to all of your site collections.

You dutifully upload it to the List Template Gallery in a site collection and create a new one. All seems well - views, etc. all look good. But then you go to add an item and you get this:

The SPListItem being updated was not retrieved with all taxonomy fields


Ah....must be a delay or something right? Wrong. When you save a template it embeds the Site Collection ID into the template. This 'breaks' the connection with the taxonomy field because it belongs to the original site. Even though the field is defined in the content hub, the field definition is broken.

Your only choice - recreate the list/library template in each site collection. A pure pain!


Wednesday, November 16, 2016

HrcClientLauncher failure - Microsoft Office 365 Support Assistant 3.5

If working with Office 365/SharePoint Online and attempting to troubleshoot something, for example Active Directory Sync you might get an issue when trying to run the "HrcClientLauncher.exe", aka the Microsoft Office 365 Support Assistant.

The symptom is that clicking it does nothing - you get a quick flash and nothing else. If you try to click on the exe and run (even and Administrator), you get the same thing.

Problem is simple - you MUST use Internet Explorer to run this - the HrcClientLauncher program is simply trying to start a download of the Support Assistant and it will not work in other browsers.

Hope that helps someone!

Friday, October 28, 2016

SharePoint 2013/2016/Online (Office 365) Importing Term Set Errors

I've come across a few common issues with importing term sets so I figured I'd share some of them here for others.

The most common error is:

Not all terms were imported successfully. Please see the server log for more information

Causes:

1) You have a comma (or the delimiter you used) somewhere in your terms
2) You have blank lines in your import file
3) You have a special character in a term, for example an accented word

BTW - the "server log" is the SharePoint server log (c:\program files\common files\microsoft shared\web server extensions\15\logs). However, you might not find much of the information useful.

The best way to figure out what the problem is is to export the term set via PowerShell and compare it to the original import. I'd recommend Stuart Roberts script which seems to work nicely and doesn't export ALL of them, just a group:

http://www.stuartroberts.net/index.php/2012/05/28/export-metadata-terms/

The one from Microsoft:

https://gallery.technet.microsoft.com/office/PowerShell-for-SharePoint-a838b5d0

BTW - for the Microsoft version, you need to do it from the SharePoint Management Shell or add the following snippet to the top of the file (under the Site Url/Output folder variables):

===================================
function Add-Snapin {
if ((Get-PSSnapin -Name Microsoft.Sharepoint.Powershell -ErrorAction SilentlyContinue) -eq $null) {
$global:SPSnapinAdded = $true
Write-Host "Adding Sharepoint module to PowerShell" -NoNewline
Add-PSSnapin Microsoft.Sharepoint.Powershell -ErrorAction Stop
Write-Host " - Done."
}

Write-Host "Adding Microsoft.Sharepoint assembly" -NoNewline
# Add-Type -AssemblyName "Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
# Disable the above line and enable the line below for SharePoint 2013
Add-Type -AssemblyName "Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Write-Host " - Done."
}
Add-Snapin

===================================
Snip courtesy of Stuart Roberts.

Another issue is when you try to import a large term set (> 2000 items) and after a period of time, SharePoint displays an error (Sorry, something went wrong):


For some reason, you cannot import more than 2000 items even though you can have up to 30,000 in one term set. The problem here is doing the import via the UI (Central Administration). It appears that either the page or the session times out when it hits that limit.

The only way to do a large term set is using PowerShell. This script is found here:

https://gallery.technet.microsoft.com/office/PowerShell-script-to-241e2d4d

WARNING: The example shown in the script is NOT correct - the script shows:

##For example : Use the following command to import Languages CSV to Default Site collection group of the site
##ImportTermSet "http://www.contoso.com" "Languages" ".\ImportTermSets\Languages.csv" "" $false

What's missing is the Term Set Group, so it should look something like this:

##ImportTermSet "http://www.contoso.com" "Languages" ".\ImportTermSets\Languages.csv" "MyGroup" $false










Saturday, October 22, 2016

SharePoint Term Set Import doesn't import description and Using Term Set Other Labels

SharePoint Term Set Import Description Doesn't Load

So importing the other day, was reminded of a problem from a while ago - it is clearly a bug and a pain so added this so others might be wary.

When using Term Sets, it can be very handy to import them via CSV - easily laid out in Excel and in fact, they give you the file format to use.

What they don't tell you is that the import is shaky:
1) I've had instances where some terms are not imported and no error reported.
2) There's no way to add 'other labels' (see below), something I love to use.
3) As some of you probably know, it often reports an import error even though all of the terms are created.

At any rate - back to the bug. When defining a term, I always put a full description; turns out this works fine as long as you do not have more than one term! If you have a 2nd term, the description is NOT imported! So for example:


The description (the State name) will not be included. Your only alternative is to decide what you want to type in by hand. There is no way to do a 'partial' import or update.

What a pain!

------

Using Term Set Other Labels

Many of my clients are not familiar with using the term set 'other labels' (a lot of SharePoint Consultants too!). Other labels are a way to allow users enter multiple names as they might know a particular term, but store only the true Term.

For example, assume you have a department called Information Systems Management, it has a department number of 1201 and most everyone calls it simply IT. For search purposes, etc. you decide you want the term 'Information Systems Management' used but some like to use the number and some like to use IT - you'd simply add them as follows:


Now when uploading/entering the field, the user can use any of them - by name:


By number:



By acronym:








Sunday, August 21, 2016

SharePoint 2013 - SharePoint 2016 - Error Creating Web Application

So, you attempt to create a web application and for some reason, it doesn't get created - you get the innocuous error screen and it appears that while the web application was created, you cannot create a site and/or the IIS site was never created.

Suddenly you notice that you cannot access Central Administration any longer - a reboot fails to fix the problem.

First you look at IIS - CA site is there, but the 'offending' application is not.

You try to run the PSCONFIG to update and it runs through successfully, but you still cannot access Central Administration.

The problem it appears is that SharePoint gets confused and can't figure out how to enumerate the applications.

The fix is to manually delete the web application via PowerShell. BEFORE you do this, you have to make sure that the SharePoint Administration service is using an account that belongs to the farm (i.e. SP Farm Account) and NOT Local System:


If it is, change it before you attempt this (change the Log On credentials and restart the service).

Open the SharePoint Management Shell (using Run as Administrator of course) and enter the command:

Remove-SPWebApplication -Identity <URL, i.e. http://somesite;<port if needed>>

The full blown command can also be used:

Remove-SPWebApplication -Identity <URL, i.e. http://somesite;<port if needed>> -DeleteIISSite -RemoveContentDatabases

When prompted, enter Y to approve of the deletion.

For more info: http://technet.microsoft.com/en-us/library/ff607891.aspx

Be aware that this may take some time to run - several minutes as a matter of fact. If it NEVER completes, there is a good possibility that the Admin Service is still running as Local System (in that case, close the PowerShell, fix the service and retry.



Service Bus Stuck on Starting

Seems Microsoft is releasing stuff without considering what it does to existing installations. I had a SharePoint farm go south because of this (and have still not recovered). After doing updates, I found that the farm was unresponsive - 'part' of the reason appears to be due to the Service Bus which was stuck on starting.

Turns out the release of .NET 4.6 is causing havoc across the board - one such issue is the Service Bus stuck in 'starting' mode.

There is a hotfix:

http://support.microsoft.com/en-us/kb/3086798


Friday, August 19, 2016

Odd error with SP 2013 Central Administration

Just thought I would add this for those that might come across this error. You have some system updates and/or have to reboot your farm (you should be doing this once a month AT LEAST anyway). You go to open up Central Administration and uh-oh - you see this:


In case you can't read the image, the  error message is:
This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect the server to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu in Microsoft SharePoint 2010 Products.
(Note - it says 2010, that's not a typo)

The problem is typically that SQL Server failed to start - this unfortunately is a common problem in 2012 R2 and I have seen it in 2014 as well. If you login to the SQL Server system, open the Services console through Administrative tools (or use Start > Run  and enter services.msc). You'll likely find that the SQL Server engine and SQL Server Agent are stopped (even though they are set to start automatically!):


You do NOT have to reboot SQL Server; just start both services, wait a minute and refresh Central Administration.
--------------------
David Sterling is the Principal Consultant for Sterling International Consulting Group, SharePoint experts with more than 100 implementations and over 13 years of experience.

We provide on site and remote consulting services for SharePoint (on premise, hybrid or purely cloud), SharePoint Online/Office 365, Azure and others. We provide multiple services including infrastructure development, information architecture, governance, business continuity and disaster recovery planning.

Contact us today at (888) 847-3679 or David direct at david_sterling@sterling-consulting.com 

Tuesday, June 7, 2016

SharePoint 2016 Timeout trying to create a service application

So you try to create a service application in SharePoint and oddly, you get a 'timeout' error. There's not much explanation provided so like most, you'll try to delete the service and recreate it but there's a good chance you'll get another timeout.

The problem is simple - the SharePoint Timer service is not running on one of the servers. Check every server and find the culprit. Once you do and start the service, return to Central Admin and delete the service that had the problem (be sure to delete any data associated as well).


If needed, you can do this via the SharePoint Management Shell (aka PowerShell) using:

$spapp = Get-SPServiceApplication -Name "<app name>" 
Then to remove the service and data:
Remove-SPServiceApplication $spapp -RemoveData
Then to remove just the service:
Remove-SPServiceApplication $spapp

Before attempting to recreate the service, double check SQL Server to make sure the database is actually gone.

SharePoint 2016 The Security Token Service is not available

This message may appear in a new SharePoint installation through the Health Analyzer. Bascially it means the STS service isn't running somewhere which is a problem for the entire farm - this can cause a lot of problems, so it's best to address it right away.

First, you'll have to check every server to ensure the service is actually available - this is done through the IIS Manager, that is, Administrative Tools > Internet Information Server (IIS) Manager.

In the IIS manager, expand the server, expand the sites then expand the SharePoint Web Services site to find the SecurityTokenServiceApplication:

Click on the SecurityTokenServiceApplication to select it, make sure you are in Content View (you won't be by default), right click on the securitytoken.svc and select Browse:


If all is good, it should display the service page:


If there is a problem, you will get the generic ASP.NET error page. 

To fix this, first, verify that all of your managed accounts have been added and the service accounts assigned accordingly (i.e. Central Administration > Security then under General Security, Configure managed accounts (to add) and Configure service accounts (to assign)).

Next (a good idea anyway), make sure your database permissions are correct - app pool accounts assigned as WSS_Content_Application_Pools, Farm account has at least SPDataAccess (or DBO if you're not that concerned about it - such as an intranet), etc.

Return to the Health Analyzer and click Reanalyze Now. If the problem doesn’t go away, it may be that one or more of the servers is not available or the SharePoint Timer Service is stopped on one of them.

If that doesn’t work either, open up the SharePoint Management Shell (always using Run as administrator) and run the psconfig command:

psconfig -cmd upgrade -inplace b2b

Do this on every server in the farm – ONE AT A TIME!

Return to the Health Analyzer and click Reanalyze Now and the problem should go away.






SharePoint 2016 The Net.Pipe Listener Adapter isn't availabile

On a new SP2016 installation, you will likely see this error in the Health Analyzer:

The Net.Pipe Listener Adapter isn't availabile.

Note, the misspelling of "Available" is how it appears in the message; guess no one checked it.

This seems to be a recurring problem with 16 in that services don't start up even though they are set to 'automatic' (the Timer Service seems this way as well).

First, verify that all of your managed accounts have been added and the service accounts assigned accordingly (i.e. Central Administration > Security then under General SecurityConfigure managed accounts (to add) and Configure service accounts (to assign)).

Next (a good idea anyway), make sure your database permissions are correct - app pool accounts assigned as WSS_Content_Application_Pools, Farm account has at least SPDataAccess (or DBO if you're not that concerned about it - such as an intranet), etc.

Next, in the Health Analyzer, try to use 'Repair automatically' and see if that fixes it (it probably won't).

If still an issue, you'll need to check the service on every server in the farm (not SQL obviously). Using Administrative Tools > Services (or Run > services.msc) and check the service:


As you can see by the above, it is set to Automatic but isn't running. Simply start it (on all servers).

NOTE: If you do NOT see the service, you have to install it (on any server where it is not found) - this can be done from here: 
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SMSvcHost.exe

However, I've found that is not enough in most cases - as you can see there are two other services (Net.Tcp) that are also set to Automatic but not running:


Start the Net.Tcp Listerner Adapter service which will also start the Net.Tcp Port Sharing Service.

Return to the Health Analyzer and click Reanalyze Now and the problem should go away.





Friday, June 3, 2016

SharePoint 2016 Installation Pre-Requisites and Error trying to use Setup.exe

For most of the 2016 installs I've done, there's been no issue however came across a really dumb one this morning setting up a new farm.

Installation of the pre-reqs went just fine or so I thought; I had to run them and the systems rebooted 3 times. One didn't request a boot; apparently, though it had run through the pre-requisites it actually did not (I found this out when I went to install SharePoint and said they were missing).

Another odd thing - after the pre-requisites were finally installed on all the servers, I started the install on the first one by opening the DVD drive (this is a VM) and tried clicking on the Setup.exe. Splash started to come up but with no color? Then it displayed an error that necessary setup files were missing.

Took a few to find it - so here's the fix - open up the Control Panel and type in AutoPlay in the search box. Click the link to 'Start or stop using AutoPlay for all media and devices'. For the 'Removable drive' option, change it to 'Ask me every time' and close the control panel.

Now return to the install media, right click on the drive and select "Install or run program from your media" - splash should come up as it is supposed to and you proceed with the installation.

One other tip - be prepared to wait a bit - the installation takes a bit longer than 2013.



Tuesday, March 22, 2016

SharePoint, BlobCache and HTTP 304's (2013/2016)

As we all know, the "BlobCache" for SharePoint is disabled by default. There are three specific lines that define this in the web.config of the site. The first is the blob cache (and location):

<BlobCache location="C:\BlobCache\" path="\.(gif|jpg|jpeg|jpe|jfif|bmp|dib|tif|tiff|themedbmp|themedcss|themedgif|themedjpg|themedpng|ico|png|wdp|hdp|css|js|asf|avi|flv|m4v|mov|mp3|mp4|mpeg|mpg|rm|rmvb|wma|wmv|ogg|ogv|oga|webm|xap)$" maxSize="10" enabled="false" />

The output cache profiles:

<OutputCacheProfiles useCacheProfileOverrides="false" varyByHeader="" varyByParam="*" varyByCustom="" varyByRights="true" cacheForEditRights="false" />

And the output cache size in MB:


<ObjectCache maxSize="100" />

All of these must be updated for a production site. First off, the Blob Cache - it must be on a drive OTHER than C: and must be enabled. In addition, it is necessary to add the 'max-age" for the blob's otherwise requests to the site will generate lots of HTTP 304's (304 is a successful pull from cache but without the max-age set to a day, it will require two hits and is a drag on performace). 

As we SHOULD all know, you never make hand changes to the web.config in SharePoint. SharePoint stores the web.config in the database and will periodically overwrite the web.config file on disk (particularly true in a multi-server environment). Changes must ALWAYS use the SPWebConfigModification object either using the Object Model or using PowerShell. You would be surprised at the supposed 'experts' that don't know this.

The following PowerShell scripts will update all three of the lines above using SPWebConfigModification. Each of these changes can be identified by the "owner" specified in the script (example: BlobCacheChg) - this allows them to be removed if necessary.

First to change the Blob Cache settings (note the settings in blue):

# SCRIPT FOR UPDATING THE BLOB CACHE:
#
# Get a reference to the object:
$configModEnable = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
# First enable the cache - set the path of the entry to change
$configModEnable.Path = "configuration/SharePoint/BlobCache"
# Get the enabled attribute:
$configModEnable.Name = "enabled"
# Set the value to true:
$configModEnable.Value = "true"
# Set the sequence (a single modification so 0):
$configModEnable.Sequence = 0
# Set the owner value:
$configModEnable.Owner = "BlobCacheChg"
# Now set the modification type (EnsureAttribute):
$configModEnable.Type = 1
#
# Get a reference to the object:
$configModSetLocation = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
# First enable the cache - set the path of the entry to change
$configModSetLocation.Path = "configuration/SharePoint/BlobCache"
# Get the location attribute:
$configModSetLocation.Name = "location"
# Set the value to true:
$configModSetLocation.Value = "e:\BlobCache\"
# Set the sequence (a single modification so 0):
$configModSetLocation.Sequence = 0
# Set the owner value:
$configModSetLocation.Owner = "BlobCacheChg"
# Now set the modification type (EnsureAttribute):
$configModSetLocation.Type = 1
#
# Get a reference to the object:
$configModSetMaxAge = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
# First enable the cache - set the path of the entry to change
$configModSetMaxAge.Path = "configuration/SharePoint/BlobCache"
# Get the max-age attribute:
$configModSetMaxAge.Name = "max-age"
# Set the value to 86400 (seconds = 24 hours):
$configModSetMaxAge.Value = "86400"
# Set the sequence (a single modification so 0):
$configModSetMaxAge.Sequence = 0
# Set the owner value:
$configModSetMaxAge.Owner = "BlobCacheChg"
# Now set the modification type (EnsureAttribute):
$configModSetMaxAge.Type = 1
#
# Apply the changes to the web application:
#
$webApp = Get-SPWebApplication –Identity http://somesite
#
$webApp.WebConfigModifications.Add($configModEnable)
#
$webApp.WebConfigModifications.Add($configModSetLocation)
#
$webApp.WebConfigModifications.Add($configModSetMaxAge)
#
# Apply the changes:
#
$webApp.Update()
#
# Update the farm:
#
$webApp.Parent.ApplyWebConfigModifications()

Updating the Output Cache setting:

# SCRIPT FOR UPDATING THE OBJECT CACHE PROFILES:
# Get a reference to the object:
$configModOCProf = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
# First enable the cache - set the path of the entry to change
$configModOCProf.Path = "configuration/SharePoint/OutputCacheProfiles"
# Get the useCacheProfileOverrides attribute:
$configModOCProf.Name = "useCacheProfileOverrides"
# Set the value to true:
$configModOCProf.Value = "true"
# Set the sequence (a single modification so 0):
$configModOCProf.Sequence = 0
# Set the owner value:
$configModOCProf.Owner = "ObjCProfileChg"
# Now set the modification type (EnsureAttribute):
$configModOCProf.Type = 1
#
# Apply the changes to the web application:
#
$webApp = Get-SPWebApplication -Identity http://somesite
#
$webApp.WebConfigModifications.Add($configModOCProf)
#
# Apply the changes:
#
$webApp.Update()
#
# Update the farm:
#
$webApp.Parent.ApplyWebConfigModifications()


Updating the Output Cache size:

# SCRIPT FOR UPDATING THE OBJECT CACHE VALUE:
# Get a reference to the object:
$configModObjCache = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
# First enable the cache - set the path of the entry to change
$configModObjCache.Path = "configuration/SharePoint/ObjectCache"
# Get the maxSize attribute:
$configModObjCache.Name = "maxSize"
# Set the value to true:
$configModObjCache.Value = "256"
# Set the sequence (a single modification so 0):
$configModObjCache.Sequence = 0
# Set the owner value:
$configModObjCache.Owner = "ObjCacheChg"
# Now set the modification type (EnsureAttribute):
$configModObjCache.Type = 1
#
#
# Apply the changes to the web application:
#
$webApp = Get-SPWebApplication -Identity http://somesite
#
$webApp.WebConfigModifications.Add($configModObjCache)
#
# Apply the changes:
#
$webApp.Update()
#
# Update the farm:
#
$webApp.Parent.ApplyWebConfigModifications()

Once these changes are made, the web.config should reflect the updates:

<BlobCache location="e:\BlobCache\" path="\.(gif|jpg|jpeg|jpe|jfif|bmp|dib|tif|tiff|themedbmp|themedcss|themedgif|themedjpg|themedpng|ico|png|wdp|hdp|css|js|asf|avi|flv|m4v|mov|mp3|mp4|mpeg|mpg|rm|rmvb|wma|wmv|ogg|ogv|oga|webm|xap)$" maxSize="10" enabled="true" max-age=86400/>

<OutputCacheProfiles useCacheProfileOverrides="true" varyByHeader="" varyByParam="*" varyByCustom="" varyByRights="true" cacheForEditRights="false" />

<ObjectCache maxSize="256" />

Now of course, you may want to remove these changes at some point - for this, you use the "Owner" specified in the scripts above.

Removing the Blob Cache changes:

# SCRIPT FOR REMOVING BLOB CACHE CHANGES:
# Get the web application:
#
$webApp = Get-SPWebApplication http://somesite
# Mod storage:
$mods = @()
# Get all modifications based on the author:
foreach ( $mod in $WebApp.WebConfigModifications ) {
       if ( $mod.Owner -eq "BlobCacheChg" ) {
              $mods += $mod
       }
}
foreach ( $mod in $mods ) {
       [void] $WebApp.WebConfigModifications.Remove($mod)
}
$webApp.Update()
$webApp.Parent.ApplyWebConfigModifications()


Removing the Output Cache changes:

# SCRIPT FOR REMOVING OBJECT CACHE PROFILE CHANGES:
# Get the web application:
#
$webApp = Get-SPWebApplication -Identity http://somesite
# Mod storage:
$mods = @()
# Get all modifications based on the owner:
foreach ( $mod in $WebApp.WebConfigModifications ) {
       if ( $mod.Owner -eq "ObjCProfileChg" ) {
              $mods += $mod
       }
}
foreach ( $mod in $mods ) {
       [void] $WebApp.WebConfigModifications.Remove($mod)
}
$webApp.Update()
$webApp.Parent.ApplyWebConfigModifications()

Removing the Output Cache size changes:

# SCRIPT FOR REMOVING OBJECT CACHE VALUE CHANGES:
# Get the web application:
#
$webApp = Get-SPWebApplication -Identity http://somesite
# Mod storage:
$mods = @()
# Get all modifications based on the owner:
foreach ( $mod in $WebApp.WebConfigModifications ) {
       if ( $mod.Owner -eq "ObjCacheChg" ) {
              $mods += $mod
       }
}
foreach ( $mod in $mods ) {
       [void] $WebApp.WebConfigModifications.Remove($mod)
}
$webApp.Update()
$webApp.Parent.ApplyWebConfigModifications()