Monthly Archives: March 2017

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.