Author Archives: Wouter Bleeker

Exception when adding user as SystemUser to SPWebApplication SPPolicy

When providing (Full Contol) access to SharePoint WebApplications using Powershell, it sometimes is a good idea to add the flag ‘System User’ to the account, because otherwise it will show up in the permission views for end-users such as the UserInfoList. In Powershell this can be done by setting the Policy attribute IsSystemUser to $True.

However, when using SAML Claims authentication this doesn’t work. I made a nice function to be able to add all types of users to the WebApplication policy during installion/configuration, but it failed whenever I issued the attribute IsSystemUser to $True for a TrustedIdentityProvider claims account.

The failure didn’t help me a lot.

PS C:\> $Policy.IsSystemUser = $True
Exception setting “IsSystemUser”: “i:05.t|adfs|administrator@wobl.it”
At line:1 char:1
+ $Policy.IsSystemUser = $True
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting

The code part I used was fairly simple and failed only when setting the ‘IsSystemUser’ to $True:

It took me a while to figure out it was only happening when using SAML Claims accounts. No help from msdn on this.
The code in the Microsoft SharePoint dll reveals why it fails. It tries to do a SID lookup using the provided username. When a regular Windows claims account is used, it decodes the claims and sets the lookup text to the decoded Windows Account. It sure is a pitty they didn’t include a specific failure message or any documentation on this part. Also there doesn’t seem to be a failure text in the SharePoint code for the stated error ‘PolicyUserCannotSetAsSystem’.

 

 

SPUserLicenseMapping case sensitive

Sometimes you find a solution to a stubborn problem, that leaves you feeling kind of silly how you could have missed that. The SPUserLicenseMapping was one of those. The problem was related to new Mysites not being created properly. The solution was to add the correct value for the SPUserLicenseMapping.
When using ADFS as a TrustedIdentityTokenIssuer, you need to use the proper claims in all properties and settings. This is also needed when you want “All Authenticated Users” to have access or rights.

The code I had used to create a new SPUserLicenseMapping, which led to the problem:

 

This resulted in the following UserLicense Mapping:

 

 

The errors I got:

User profile property ‘EduUserRole’ not found from from MySitePersonalSiteUpgradeOnNavigationWebPart::GetUserRoleFromProfile(). This should indicate that the current user is not an edudation user.

Skipping creation of personal site from MySitePersonalSiteUpgradeOnNavigationWebPart::CreatePersonalSite() because one or more of the creation criteria has not been met. [SPWeb Url=https://sharepoint.company.com/Person.aspx?accountname=i:05.t|adfs|user@company.com]  https://sharepoint.company.com/Person.aspx?accountname=i:05.t|adfs|user@company.com]Self-Service Site Creation == True  Can Create Personal Site == False  Is user licensed == False  Storage&Social UPA Permission == True  Site or Page or Web Part is in design mode == False

Exception during creation of personal site from MySitePersonalSiteUpgradeOnNavigationWebPart::CreatePersonalSite(). [SPWeb Url=https://sharepoint.company.com/Person.aspx?accountname=i:05.t|adfs|user@company.com]  Message: Thread was being aborted.  Stack Trace:
at System.Threading.Thread.AbortInternal()
at System.Threading.Thread.Abort(Object stateInfo)
at System.Web.HttpResponse.AbortCurrentThread()
at Microsoft.SharePoint.Utilities.SPUtility.Redirect(String url, SPRedirectFlags flags, HttpContext context, String queryString)
at Microsoft.SharePoint.Portal.WebControls.MySitePersonalSiteUpgradeOnNavigationWebPart.<>c__DisplayClass6.<CreatePersonalSite>b__4()
at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass5.<RunWithElevatedPrivileges>b__3()
at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)
at Microsoft.SharePoint.Portal.WebControls.MySitePersonalSiteUpgradeOnNavigationWebPart.CreatePersonalSite(UserProfile userProfile, Uri personalSiteUrl)

Call to PersonalSiteInstantiationState::Init for i:05.t|adfs|user@company.com with IsUserSelf(): True, IsProfileAdmin: False, resulted in m_bCanUseStorage: True, m_bCanUseMicrobloggingAndFollowing: True, m_bCanPersonalize: True, m_bCanFollowTagsAndUsers: True, [MySiteHost Found?=True CompatLevel=15 Licensed?=False URL=https://sharepoint.company.com:443] StackTrace:
at Microsoft.Office.Server.UserProfiles.UserProfile.PersonalSiteInstantiationContext.Init(UserProfileManager objManager, UserProfile userProfile, SPSite mySiteHost)
at Microsoft.Office.Server.UserProfiles.UserProfile.PersonalSiteInstantiationContext..ctor(UserProfileManager objManager, UserProfile userProfile)
at Microsoft.Office.Server.UserProfiles.UserProfile.InitPersonalSiteInstantiationContext()
at Microsoft.Office.Server.Microfeed.MicroBlogEntity.get_PersonalSiteNotFoundCode()
at Microsoft.Office.Server.Microfeed.MicroBlogEntity..ctor(UserProfile userProfile, MicroBlogEntity currentUser)
at Microsoft.Office.Server.Microfeed.SPMicrofeedManager..ctor(UserProfile userProfile, SPServiceContext context, SocialAdminCapability socialAdminCapability)
at Microsoft.Office.Server.Social.SPSocialFeedManager.<>c__DisplayClass8.b__6()
at Microsoft.Office.Server.Social.SPSocialUtil.InvokeWithExceptionTranslation(ISocialOperationManager target, String name, Action action)
at Microsoft.SharePoint.Portal.WebControls.MicroFeedWebPart.OnPreRender(Object sender, EventArgs e)
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

Property get of UserProfile.PersonalSiteInstantiationState for user i:05.t|adfs|user@company.com. Returning: ErrorSelfServiceSiteCreateCallFailed

FeedsWebPart: PersonalSiteInstantiationState for accountName i:05.t|adfs|user@company.com fetched is ErrorSelfServiceSiteCreateCallFailed

 

The problem was caused by the EncodedClaim “c:0(.s|true” which is displayed as ClaimValue. This value is case sensitive and needs to be “True“.

Solution
The right code:

This provides the correct UserLicense Mapping:

 
Oh and by the way: adding UserLicenseMapping for the SharePoint Standard License to all users is a good choice to prevent many errors in your logfiles, while it doesn’t actually seems to give any errors to end-users.

SiteHealthCheck and Deleted Sites

When performing an upgrade or migration of an on premise SharePoint environment, it is important so check everything in the Farm. This particularly includes contentdatabases and sites. I ran into this when debugging a site that was partly deleted. I couldn’t get it removed and then tried to determine what the problem was, the SPSiteHealth check didn’t help me in this case. Eventually I force removed the site and after some timerjob had ran the site was gone.

 

Some examples to check sites for issues related to upgrades and migrations:

 

You can also have SharePoint repair the specific site for you:

 

 

 

DESCRIPTION
The Repair-SPSite cmdlet runs one or all site collection health checks on the site collection and its contents. This cmdlet automatically repairs issues that it finds.

Run the Test-SPSite cmdlet for reports of rules which were run and a summary of the results.

 

Note: the only repairable SiteHealthRule is the “Missing Galleries” rule.

More info:
You run the health checks manually to prepare for an upgrade. In addition, the health checks are run automatically in repair mode when you start to upgrade a site collection. You can also run the health checks at any time to verify that a site is working as expected. The site collection pre-upgrade health checks examine a site collection and list potential upgrade issues, such as missing or unsupported elements. For example, the results itemize customized files so that you can identify the custom file and reset it to the default template in the site definition, if you want. After you run the checks, a report lists potential issues. The report also has information about how to address the issues.

MSDN Article

 

 

About the site delete action, read this article from Bill Baer, it explains the internals concerning the site deletion in SharePoint 2010 and up worth. Next up, read this article which provides some Powershell commands to really delete your site. (Or just use it: Get-SPWebApplication | Get-SPDeletedSite | Remove-SPDeletedSite .)

It involves an SPTimerJob “Gradual Site Delete” (Microsoft.SharePoint.Administration.SPSiteDeletionJobDefinition) which is scheduled daily at night.

 

Discovering the SPTimerService and PreferredTimerServiceInstance in SharePoint with Powershell

Recently we had installed a new SharePoint 2013 On Premise farm. Everything worked great with custom features and permissions and so on, however suddenly a Health Monitoring Rule came knocking about some missing dependencies. I fixed this specifically a few weeks ago, but now it reappeared without us changing anything that could trigger this. When I reran the Health Analyzer Rule, it was OK again.

Upon investigation, it seemed the corresponding SPTimerjob was run on a back-end server the time it got the error messages. When it turned OK it was running on a Front-End server. The message itself was not unfamiliar, it can also be triggered by the Powershell command “Test-SPContentdatabase”.

When I ran this Powershell command on a Front-End server, it reported no problems, but when I ran it on a back-end server, it reported the same Missing Dependencies warnings (Missing Templates, Missing Features, Missing Webparts, etc).

This Health rule “Missing server side dependencies” is run once a week, the scope of this rule can be set to “Any server” or “All servers”. This doesn’t help us in our case.

Scope options for Health Analyzer Rules

Scope options for Health Analyzer Rules

The cause is that our back-end servers do not have the ServiceInstance “Microsoft SharePoint Foundation Web Application” running. Also the custom solutions are not installed on our back-end server (related to the webapplication scope of some of them). Testing to load our custom DLL proved to produce errors on our back-end SharePoint servers:

 

 

So I searched for a way to have this Health Analyzer Rule run only on the Front-End servers, and of course I want to do it with Powershell.

I have found two ways of doing this:

  1. Setting the SPContentDatabase property “PreferredTimerServiceInstance” to a specific TimerService that lives on a specific Front-End. Read more on it at https://msdn.microsoft.com/.
  2. Changing the SPTimerServiceInstance property “AllowContentDatabaseJobs” to False on the servers on which I don’t want this rule. Read more on it at https://msdn.microsoft.com/.

Reading the remarks on the AllowContentDatabaseJobs property at the second MSDN page definitely demonstrates my finding:

Note that if a server is set as the “preferred” server for content database timer jobs, then setting this property to false will cause an exception.

 

To get some more background info on the PreferredTimerServiceInstance, read the answer from Roger Cormier at this MSDN forum post.

 

 

So how do we set these properties?

First off, we need to look at the SPTimerServiceInstances in our Farm. We can get these with either one of the following commands:

 

To get the specific TimerService Instance on the current server we can use the following where clause:

 

The property on the ContentDatabases is easily accessible, just get an SPContentDatabase object with the appropriate Powershell command “Get-SPContentDatabase”. The property “PreferredTimerServiceInstance” can be read and set normally.

 

So, to set the property on all contentdatabases to the TimerService instance on the current server, we can use the following loop.

 

 

Now to get or set the AllowContentDatabaseJobs property requires some more advanced Powershell and reflection again (read this article for my explanation on the GetMember/Invoke construction). Notice I use the Farm TimerService Instances to iterate through and invoke the get method on each one.

 

Finally I set the value to false on the TimerService instances on all servers except the current server:

 

Keep in mind that it is better to have more than 1 server as possible TimerService Instance, because when the preferred instance fails, we don’t want more trouble.

 

Don’t forget we need to Update and Restart the timerservices as per MSDN remark on the AllowContentDatabaseJobs property:

Powershell to get SharePoint 2013 Recent crawl rate and recent query rate

Retrieving SharePoint Enterprise Search Service Application monitoring information through Powershell requires some deeper digging than I imagined! We can get the last search crawl results from the CrawlHistory, we can get the current CrawlState (or CrawlStatus, 100% equal, see below), but to get the information that is shown in Central Administration under Search Administration proved to be a tough one. I really wanted to have the recent crawl rate and recent query rate. This article also provides some insight in using the hidden methods inside DLL’s, in this case the Microsoft.Office.Server.Search.dll.

The solution

Eventually through using reflection with ILSpy and some c# logic I managed to get it. In the end the code seems fairly simple. We need to call a nonpublic method “get_Monitoring“, using bindingflags, which retrieves an object of the type “Microsoft.Office.Server.Search.Administration.SearchServiceApplicationMonitoring”, which provides us with the properties QueriesPerMinute (recent query rate) and CrawlDocumentsPerSecond (recent crawl rate).

 

 

 

Get-SPEnterpriseSearchServiceApplication QueriesPerMinute & CrawlDocumentsPerSecond

Search Service Application: Search Administration -vs- Powershell QueriesPerMinute & CrawlDocumentsPerSecond

 

ILSpy SearchServiceApplicationMonitoring Reflection

Using ILSpy to find hidden methods in the SharePoint DLL’s

 

 

An explanation of how this works

Each (SharePoint) object in Powershell, like an SPWebApplication or an SPServiceApplication, has certain public properties and methods. You get these by simply using the dot and tab, using ‘| Get-Member’, or just ‘| Format-List’.
Each (SharePoint) object can also have a set of nonpublic, private or protected properties and methods. To get these, we need to invoke some .NET within Powershell. We do this on the Type. So we get an object, get it’s type ‘.GetType()’ and then we use ‘.GetMembers()’. However, like I said, when we are looking for nonpublic/private/protected methods and properties, we need to use a specific set of bindingflags. To get all members/methods/properties, we need to use all bindings. We can set this as a variable, and then call the ‘.GetMembers()’ method using that variable. Once we have found an interesting method, we need to invoke it on the type object, for instance with ‘.GetType().InvokeMember(…..)’. More info on this .NET C# logic at msdn.

 

 

CrawlStatus vs CrawlState

When working with the Search Service Application Content Sources, we can find some interesting information on the status and we can also perform actions on this specific content source. Looking at the properties of a Crawl Content Source you might have wondered, what do they mean. Quite funny to have CrawlState and CrawlStatus properties, which you would expect to be different (why else would you have 2 properties), when they are exactly the same.

 

 

Analyzing Distributed Logon Token Cache Exception

Read carefully when you catch this error “ErrorCode<ERRCA0017>:SubStatus<ES0006>:There is a temporary failure.”, because in our case it was a misconfigured AD Kerberos Service Principal Name for the service account which runs the Distributed Caching Service.
In that case you get the above mentioned error with at some point in the stacktrace the message “The target principal name is incorrect.”, you are in the same situation as we were.
 

 

Stacktrace

 

Unexpected error occurred in method ‘GetObject’ , usage ‘Distributed Logon Token Cache‘ – Exception ‘Microsoft.ApplicationServer.Caching.DataCacheException: ErrorCode<ERRCA0017>:SubStatus<ES0006>:There is a temporary failure. Please retry later. (One or more specified cache servers are unavailable, which could be caused by busy network or servers. For on-premises cache clusters, also verify the following conditions. Ensure that security permission has been granted for this client account, and check that the AppFabric Caching Service is allowed through the firewall on all cache hosts. Also the MaxBufferSize on the server must be greater than or equal to the serialized object size sent from the client.) —> System.ServiceModel.Security.SecurityNegotiationException: A call to SSPI failed, see inner exception. —> System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. —> System.ComponentModel.Win32Exception: The target principal name is incorrect.
 

 

You might try the path of verifying all settings and timeouts.

 

AppFabric DistributedCache check

Some Powershell examples of getting AppFabric Distributed Cache Instances.
Work-in-progress article…
 

Basic Cluster Info:

CacheStatistics per CacheHost

CacheStatistics per NamedCache

 

 
Very Basis Cache Cluster Info:

 

 

Advanced CacheHost Status, where Distributed Cache resides on all SharePoint Front-End servers which do not host the Central Administration.

 

 

Different examples of Cache Configuration

Cache Allowed Clients should always return the default by SharePoint created and populated groups

 

CacheClient Configuration might seem difficult to interpret when using the command Get-SPDistributedCacheClientSetting, however using the .NET namespaces it is translated to human readable time values:

Recreate OfficeWebApps Farm when patching/upgrading

A powerful, yet easy solution to simplify the process of recreating the OfficeWebApps Farm after an upgrade. As mentioned in the article from Microsoft Technet, when you want to apply a patch and/or upgrade to the OfficeWebApps software, you need to remove the OfficeWebApps Machine (Remove-OfficeWebAppsMachine) prior to the upgrade and recreate the Farm (New-OfficeWebAppsFarm) afterwords.
This seems a bit uneasy, because you need to get every parameter of the current Farm (Get-OfficeWebAppsFarm). Also you need to do this every time you update to the latest ServicePack or Cumulative Update.

This solution automates that part, by writing the current config to CSV and loading it in to recreate the Farm with exactly the same config.

 

The first part is just plain and simple, export the config to CSV, don’t forget any Host config (allowed domains), than remove the OfficeWebApps Machine.

The next part recreates the OfficeWebApps Farm based on the CSV, which checks the parameters of the “New-OfficeWebAppsFarm” and converts booleans from the CSV where needed.

By using a hashtable for the parameters, it is easy to use it with the “New-OfficeWebAppsFarm” command. This technique (using a ‘@’ in front of the hashtable variable) is called splatting, check this blog for more on that.

 

Happing upgrading!

 

New-SPMetadataServiceApplication hangs

This SharePoint Powershell command stalls: “New-SPMetadataServiceApplication”

Using the AutoSPInstaller script, the deployment hangs.
The script finally stalls with the following:

Provisioning Managed Metadata Service Application
Creating SharePoint Hosted Services Application Pool…
Starting Managed Metadata Service:
Starting Metadata Service Instance…
Waiting for Metadata service…Online
Creating Metadata Service Application…

 

ULS Log:

Blocking until timer job ‘—GUID—‘ has completed.

 

Get-SPTimerJob doesn’t give any result when referencing the mentioned GUID.

After an undetermined period of time, it finally errored out with:

 

Solution

Solved by a re-run after deleting the “half” created service application and adding/activating the Registry/Policy item DisableForceUnload.

Registry entry:

 

Powershell:

 

Manual GUI setting:
Local Group Policy Editor > Local Computer Policy > Computer Configuration > Administrative Templates > System > User Profiles > “Do Not Forcefully Unload The Users Registry At User Logoff” > Enabled

 

Group Policy Filename:
UserProfiles.admx > “Do not forcefully unload the users registry at user logoff”

 

Other people with the same problem: autospinstaller.codeplex.com/workitem/19457

Getting Use-CacheCluster to work on a SharePoint server without the AppFabric Distributed Cache Role/Component

You probably have encountered it already some time ago. You want to check the status of your Distributed Cache Cluster and you login to a back-end server where there is no Distributed Cache component.
You open up Powershell and start with Use-CacheCluster. It fails. You failed. You need to login to a server which is an active member of the Distributed Cache Cluster to get the status, configuration, etc.

Now there is a simple solution which does not effect your application.

 

Some examples you might get when trying to connect to the AppFabric Distributed Cache cluster from a SharePoint server:

 

I have been on a gooze chase for a while because of articles like this:


 

use-cachecluster
use-cachecluster -Provider “System.Data.SqlClient” -ConnectionString “Data Source=dbmachine\instance;Initial Catalog=DatabaseName;Integrated Security=true”

http://blog.milrr.com/2012/05/code-appfabric-diagnostic-powershell.html


 

Use-CacheCluster
Sets the context of your Windows PowerShell session to the desired cache cluster.

When you start a Windows PowerShell session, you must first run this command. If it is on a cache host, you run the command with no parameters, because the parameters are taken from the cache configuration on the computer. If you are running it from a non-host computer, you can use the parameters below to specify the desired cache cluster.

Parameter (alias) descriptions are as follows:

Provider (P): The provider that is used to store the cluster configuration settings. This can be eitherSystem.Data.SqlClient or XML depending on how the configuration information is stored.
ConnectionString (C): The connection string to the database or location of the XML configuration file.

https://msdn.microsoft.com/en-us/library/ff718177(v=azure.10).aspx


 

 

How to do it

Thankfully, there is a solution:
The Use-CacheCluster can be helped with the directions where to find the cluster configuration. All it needs is some registry entries.
No problems or errors will occur, you are not activating services or changing the config within SharePoint. Just the registry on the server(s) where you want to be able to look at the Cache Cluster.
This is, because every SharePoint 2013 server gets the same AppFabric installation, because its a prerequisite component.
That means the Powershell modules, DLL files and basic registry entries are already in place.

We only need to add a few properties.

 

We can create these very easy:

 

Now, when we use Use-CacheCluster on a SharePoint 2013 server where Distributed Cache is not configured, it works!