Radi Atanassov

SharePoint MCM, MVP, MCT and owner of OneBit Software

Silverlight install errors and changing the default Program Files location (NOT SharePoint)

I was having problems installing both Flash and Silverlight on a new build, and thought I might share my situation.

I have an SSD drive (C:\)and another 7200 RPM mechanical HDD (D:\). I did quite a bit reading on how to optimize my SSD’s lifetime, and many sources say that we shouldn’t worry about taking much care of our SSD’s. They live longer now + mine has a 3 year warranty. I still wanted to implement some tweaks, and I also wanted to place some rarely used program files on my mechanical drive. Things I did: Move page file to D: (and reduce it as I have 16GB RAM), put browser and Windows temp files on D:, set download folder to D:, and some others which I don’t recall anymore (: Many might ask why, but that is for another discussion.

The challenge I was having is setting Program Files to default on D:. I did not do this during the installation of Windows 7, and I couldn’t find a “supported” way change from C: to D:, so I went ahead and changed the registry key, expecting something to fail at one point in time. Everything seems fine and it has been 2 months and I have passed many installations, but the first things that failed we’re Flash and Silverlight. Both addons gave meaningless error messages.

Reg Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir AND \ProgramFilesDir (x86)

The fix is easy, change the registry key back to C:, restart, install them and return it to D: I want it to stay D: so it is the default when installing applications. Note, I actually had to restart, but you could probably get away with log off/log on.

So to close this off, changing the default program files directory is not supported, it may be fine at first, but you might get nasty errors later on. Plan this during the installation of Windows 7, rather than forget like me.

And just as a side note, I’ve always been a fan of hacking and customizing my OS… I have done various other things to it, some I understand, but some that I don’t and shouldn’t do. I installed some Lenovo software/drivers, then decided to modify my start button and chrome, and now Windows 7 thinks it’s not genuine and it keeps reminding me! I can live with that (I probably have 3 Windows 7 licenses and 1 laptop), but it should stick as a warning to everyone (:

SharePoint 2010 Search: Some Managed Properties cannot be included in queries

A colleague today showed me a problem he was having with full text search queries. All he was doing is including the ContentType managed property in the search query, which returned a Microsoft.Office.Server.Search.Query.InvalidPropertyException.

The reason for this is that the Content Type field is now marked as non-retrievable. The ManagedProperty class has a “Retrievable” property, which according to this MSDN article, specifies whether it can be used in queries: microsoft.office.server.search.administration.managedproperty.retrievable.aspx

According to this blog post, it used to be retrievable in SharePoint 2007. Definitely a gotcha - most people would think this is possible, and most may also sell it in a client meeting.

The problem is that you cant set it to true… I currently have no solution for this, but I thought I might post a list of ALL managed properties (in a default installation with very few content) that have Retrievable set as False.

PowerShell script to check properties:

Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication "Search Service Application" | where {$_.Retrievable -eq $false}



OK so I looked into it further, I tried setting it in the Search SA to be included in all results, but that didn’t work:



And adding it in the advanced search web part also doesn’t work:


The query will return no results. Trying to set the property to True in PowerShell or the OM still gives the same error.

So, the only workable solution that is flying around is the one posted on the MSDN forums. It still, however, is a workaround that can’t be used in ALL situations out there. This is not great, as one would think the ContentType field is something you would want to include in your search results.

Please let me know if you find any other solutions.

Developing custom Health Rules for SharePoint 2010

What are health rules?

SharePoint 2010 has a new feature called the Health Analyzer and it has Health Rules. Each rule checks a particular metric within the SharePoint farm, and Central Administration provides an interface to see problems, warnings, and rule definitions. Administrators can subscribe to rules so they get alerts when the rule fails. Administrators cannot create custom rules, but developers can.

This is what the interface looks like:


Why should architects and developers consider them?

Administrators might ask you to create rules to monitor specific things on a server.

Further to that, developers can create rules to monitor their own solutions. Certain aspects of a solution might be problematic and require attention after time - for example a growing list. A custom rule can monitor this list, and notify certain people if a threshold is being passed.

High-Level steps to create a custom Health Rule:

  1. Create a class that inherits from Microsoft.SharePoint.Administration.Health.SPHealthAnalysisRule
  2. Override the required methods in SPHealthAnalysisRule. Check() is where the action happens, but also pay attention to SPHealthAnalysisRuleAutomaticExecutionParameters
  3. Create a feature to register the rule definition with SharePoint
  4. (Optional) use a Console Application to test your rule code while developing it. This is much more convenient when you need to debug with Visual Studio 2010.

Example Solution:

I have put together a template you could reuse to build custom health rules. My example pings each database server from each WFE and fails if the ping is greater than 1ms. Download the code from the bottom of the post.

Here is my schedule and scope configuration (see notes below for more details):

  1. public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
  2. {
  3.     get
  4.     {
  5.         SPHealthAnalysisRuleAutomaticExecutionParameters execParams =
  6.             new SPHealthAnalysisRuleAutomaticExecutionParameters();
  8.         execParams.Schedule = SPHealthCheckSchedule.Hourly;
  9.         execParams.RepairAutomatically = false;
  10.         execParams.Scope = SPHealthCheckScope.All;
  11.         execParams.ServiceType = typeof(SPWebService);
  13.         return execParams;
  14.     }
  15. }

I use the following code to get all Database servers:

  1. //Get the Database Service
  2. SPDatabaseService spdbservice =
  3.     SPFarm.Local.Services.GetValue<SPDatabaseService>();
  5. //Get all instances of the Database Service
  6. SPServiceInstanceDependencyCollection dbServices = spdbservice.Instances;
  8. //fail the test if no DB servers are found (network is dead)
  9. if (dbServices.Count == 0) return SPHealthCheckStatus.Failed;
  11. //The following will enumerate all instances so we can get the servers hostname
  12. foreach (SPDatabaseServiceInstance instance in dbServices)
  13. {
  14.     SPServer dbServer = instance.Server; //each of these is a DB server
  16.     if (!PingServer(dbServer.Name)) //ping it
  17.     {
  18.         failedPings++;
  19.     }
  20. }

And here is my ping method:

  1. private static bool PingServer(string serverHostName)
  2. {
  3.     bool returnValue = false;
  5.     Ping dbPing = new Ping();
  6.     PingReply reply = dbPing.Send(serverHostName);
  8.     if (reply.Status == IPStatus.Success)
  9.     {
  10.         long latency = reply.RoundtripTime;
  12.         if (latency <= 1) { returnValue = true; }
  13.     }
  15.     return returnValue;
  16. }

Here is the Feature Receiver code to register the rule:

  1. public override void FeatureActivated(SPFeatureReceiverProperties properties)
  2. {
  3.     Assembly currectAssembly = Assembly.GetExecutingAssembly();
  5.     try
  6.     {
  7.         SPHealthAnalyzer.RegisterRules(currectAssembly);
  8.         //SPHealthAnalyzer.UnregisterRules(currectAssembly);
  9.     }
  10.     catch (Exception ex)
  11.     {
  12.         throw new Exception("Registering Health Rules from "
  13.             + currectAssembly.FullName + " failed. " + ex.Message);
  14.     }
  15. }

The commented out line lets you unregister the rule. You should do this in the Deactivating method.

Important Points in configuring the scope and schedule of you rule:

  • The ServiceType property - this lets you specify a particular SharePoint service that is required on servers that are to run this rule. For example, you can use this property to specify that your rule should only run on machines running Excel Services.
  • The Scope property - this defines whether the rule will run on ALL servers, or ANY servers. If set to ANY, it will run on the first server that is running the SharePoint Service specified in the ServiceType property. If set to ALL, it will run on all servers running that service.
  • In my example I am pinging the DB servers from ALL servers running the SharePoint Web Service (web front ends). Any application server not running this service will not fire this rule. You might want to change this to SPTimerService or whatever suits your needs.

Other things of interest:

  • Central Administration has a “HealthRules” list, which has it’s own List Template type (SPHealthRulesList).
  • The SPHealthAnalyzer object maintains this feature.
  • The AddItem method of the SPHealthRulesList does two things: Creates an Item in the List, then registers an SPHealthAnalyzerJobDefinition Timer Job. There is one of these for each schedule, service and scope. This can be seen in the Timer Job definitions page:


  • The implementation of this can be seen in the AddItem method with Reflector”


Further links:

Download source code: Community.SharePoint.zip (you must click the download button on the Live page...)

Hope this helps !