Sitecore Coveo free edition using rules engine to filter result

Before reading please be aware that the rules are disabled in the Free edition because they are part of the Ranking Editor feature sold in the Enterprise edition. Using them to look up how queries look like with the Free edition is OK if you then use them like this But, you cannot give this feature to the End Customer with the Free edition.

Site search is an important part of functionality from a website, some website even make their main navigation functionality for site visitors – think of airlines or eCommerce website.

Sitecore has a couple of options to built a site search functionality which can be achieved by using Lucene and SOLR. There’s another option which is using Coveo, an enterprise search provider that has an integration module with Sitecore. Recently Coveo released the free edition for Sitecore which I decided to try out.

I was impressed by the result, I particularly like how easy it is to set it up given that Coveo has predefined renderings that’s ready to use. I literally just create a new page with Coveo search result layout with it’s predefined renderings, add some new renderings to give the search result page some specific filter, and sorting functionality. It just works.

All looks good so far but then I encounter a problem where I want to set a default filter that set the results based on a specific template. A use case would be if I want to create a search result page for a News section where I want to build search result page that by default listed the results only based on News template.

Coveo free edition has no support for content editor to change the filter using the Sitecore rules, but for learning purposes you can do the following to enable it to know more about how Coveo build it’s queries.

First off let’s duplicate Coveo Search Parameter item in /sitecore/templates/CoveoModule/Search/Coveo Search Parameters. Create a new field called CustomFilterExpressionRules and set the type to Rules with the source field set to “rulespath=/sitecore/system/Settings/Rules/Coveo Search Rules&hideactions=true&includecommon=false”


The duplicate Coveo Search Model, you can find this item in /sitecore/layout/Models/Coveo/Search Model


Here I give it a name as Search Model Custom and set the Model Type to “MyApp.SearchModel, MyApp”

class MyApp.SearchModel

public class SearchModel : Coveo.UI.Mvc.Models.SearchModel, ISearchModel
 private IEnumerable<CoveoRule> _customFilterRules;

 public IEnumerable<CoveoRule> CustomFilterRules
 get { return _customFilterRules ?? (_customFilterRules = GetRulesField("CustomFilterExpressionRules")); }

 public new string HiddenExpression
 var searchContext =
 var str = "";
 if (CustomFilterRules.Any())
 str = RulesHelper.GetQueryExpression(CustomFilterRules, searchContext);
 if (!string.IsNullOrEmpty(str))
 str = " " + str;
 return str + GetExcludedTemplatesExpression();

 public override ErrorReport ValidateModel()
 var errorReport = base.ValidateModel();
 ValidateRules(errorReport, CustomFilterRules, ValidateRule);
 return errorReport;

 private void ValidateRule(ErrorReport errorReport, CoveoRule rule)
 if (rule.Condition != null)
 errorReport.AddError(Labels["The rule must have a condition."]);

 private void ValidateRules(ErrorReport p_Report, IEnumerable<CoveoRule> p_Rules,
 Action<ErrorReport, CoveoRule> p_ValidationMethod)
 foreach (var coveoRule in p_Rules)
 var p_SubReport = new ErrorReport();
 p_ValidationMethod(p_SubReport, coveoRule);
 p_Report.AppendAsGroup(coveoRule.Name, p_SubReport);

 private IEnumerable<CoveoRule> GetRulesField(string fieldName)
 var list = new List<CoveoRule>();
 var stringParam = ParametersHelper.GetStringParam(fieldName);
 if (!string.IsNullOrEmpty(stringParam))
 list.AddRange(RulesHelper.ParseRules(SitecoreContext.GetCurrentDatabase(), stringParam));

 return list;

 private string GetExcludedTemplatesExpression()
 var list = new List();
 if (!IncludeBucketFoldersInResults)
 list.Add(new Guid("{ADB6CA4F-03EF-4F47-B9AC-9CE2BA53FF97}").ToString("D"));
 if (!IncludeMediaFoldersInResults)
 list.Add(new Guid("{FE5DD826-48C6-436D-B87A-7C4210C7413B}").ToString("D"));
 var str = "";
 if (list.Any())
 str = " " + 
 string.Format("NOT {0}==(\"{1}\")", ToCoveoFieldName("templateid"),
 string.Join("\",\"", list.ToArray()));
 return str;

We have the custom rendering parameter and custom search model now we need to create a new search view rendering that uses this custom parameter and model. Go to /sitecore/layout/Renderings/Coveo/Coveo Search View . Duplicate the item and name it Coveo Search View Custom. Set the model field to our custom model item and the rendering parameter to our custom parameter item.


Now to test it, I created a new page using the Coveo Search (MVC) insert option and then change the Search View rendering with the Search View Custom that I made.


Edit the properties, it shows up a dialog window where we can update the filter based on the custom field that we previously created.

The result


The key here is the HiddenExpression property, it returns the filter expression that Coveo understand based on the Rules value that we’ve set. In the above result it output the following value to filter the result” (@falltemplates99785=\”f1828a2c7e5d4bbd98ca320474871548\”) NOT @ftemplateid99785==(\”adb6ca4f-03ef-4f47-b9ac-9ce2ba53ff97\”,\”fe5dd826-48c6-436d-b87a-7c4210c7413b\”)”

Sitecore 8 adding edit meta data button in experience editor

Are you still making your content author to edit the content of a page using content editor? then stop.

For content author in Sitecore the best way for them to edit a page is to use Sitecore Experience Editor. This way they can focus on editing the content on the page with visual indication what would their changes would look like. However there are some cases where content can’t be edited on the page because they are not displayed on the page itself, Metadata information is such a case.

There are some guide already out there to set up an edit meta data button in page editor in Sitecore 7 and below, and here I would like to do the same in Sitecore 8. This is based on the guide that I’ve found on which can be reused to create other type of functionality.

First you need to install Sitecore Rocks, because in Sitecore 8 the interface is built using SpeakUI you may find it quite different with how you usually set up a new button in Sitecore 7 and below. I’ve also found it easier to create a SpeakUI component using Sitecore Rocks, so you definitely should check it out. After you’ve installed Sitecore Rocks and setup a connection to the Sitecore website you should see the following screen.



Expand the core database and go to sitecore->content->applications->webedit->ribbons->webedit

Here you can see a couple of familiar strips which is what being displayed on the experience editor



We want to add a new button to edit meta data here, so go in Sitecore Rocks and under the WebEdit node follow this steps

  • Add a new Page Properties strip
    • Add a new item with the template of Strip.
    • Set the header to “Page Properties” and the ID to “PagePropertiesStrip”
    • In Sitecore Rocks select tasks and design layout then add a new rendering of type Strip
  • Add a new Hidden Content chunk
    • Under the new Page Properties strip add a new item with the template of Chunk
    • Set the header to “Hidden Content” and ID to “HiddenContentChunk”
    • In Sitecore Rocks select tasks and design layout then add a new rendering of type Chunk
  • Add a new Edit Meta data button
    • Under the new Hidden Content chunk
    • Set the header to “Edit Meta Data” and ID to “EditMetaDataButton”
    • In Sitecore Rocks select tasks and design layout then add a new rendering of type LargeButton
    • Edit the rendering properties of the LargeButton
      • Set AccessKey to Meta Keywords|Meta Description (this the meta data fields that I’ve setup in Sitecore)
      • Set the Click property to trigger:button:click
      • Set the Command to LaunchFieldEditor
      • Set the PageCodeScriptFileName to the path of the LaunchFieldEditor.js file is


What it currently looks like so far



At this stage we still need to register the command to handle the edit meta data button functionality so let’s go ahead and do that.

<configuration xmlns:patch="">
 <request name="ExperienceEditor.GenerateFieldEditorUrl" type="Website.Modules.Components.ExperienceEditor.FieldEditor.GenerateFieldEditorUrl, Website.Modules"/>

The GenerateFieldEditorUrl class

public class GenerateFieldEditorUrl : PipelineProcessorRequest<ItemContext>
 public string GenerateUrl()
 var fieldList = CreateFieldDescriptors(RequestContext.Argument);
 var fieldeditorOption = new FieldEditorOptions(fieldList);
 //Save item when ok button is pressed
 fieldeditorOption.SaveItem = true;
 return fieldeditorOption.ToUrlString().ToString();
 private List<FieldDescriptor> CreateFieldDescriptors(string fields)
 var fieldList = new List<FieldDescriptor>();
 var fieldString = new ListString(fields);
 foreach (string field in new ListString(fieldString))
 fieldList.Add(new FieldDescriptor(RequestContext.Item, field));
 return fieldList;
 public override PipelineProcessorResponseValue ProcessRequest()
 return new PipelineProcessorResponseValue
 Value = GenerateUrl()

The LaunchFieldEditor.js

define(["sitecore"], function (Sitecore) {
Sitecore.Commands.LaunchFieldEditor =
 canExecute: function (context) {
 return true;
 execute: function (context) {
 //context.currentContext.argument = context.button.viewModel.$el[0].firstChild.alt;
 //context.currentContext.argument = context.button.viewModel.$el[0].title;
 context.currentContext.argument = context.button.viewModel.$el[0].accessKey;
 Sitecore.ExperienceEditor.PipelinesUtil.generateRequestProcessor("ExperienceEditor.GenerateFieldEditorUrl", function (response) {
 var DialogUrl = response.responseValue.value;
 var dialogFeatures = "dialogHeight: 680px;dialogWidth: 520px;";
 Sitecore.ExperienceEditor.Dialogs.showModalDialog(DialogUrl, '', dialogFeatures, null);

After all have been setup correctly the content author can now edit the meta data button through the experience editor.


Sitecore 8 WFFM MVC – Form Report display no data

We’re using Sitecore 8 update 2 and WFFM 8.0 rev. 150224, the issue that we have is that no matter how often we input the form data and submits it, the form report in Sitecore backend keeps saying that there’s no data to display. Checking in to the analytics database in MongoDB also shows empty FormData collection.

Long story short after contacting Sitecore support, it seems that we need to add the following code



It’s mandatory to put that bit of code in your layout so that Sitecore analytics can work properly. It also reminds me of an issue that I had with a similar fix

While investigating this issue I also found a couple of things that can help you test your WFFM forms

  • Any submitted form data will be flushed after the session has expired which by default the session timeout is 20 minutes, for quick testing purposes we can change the value which is specified in the web.config to for example 2 minutes
    • <sessionState mode=”InProc” cookieless=”false” timeout=”2″ sessionIDManagerType=”Sitecore.FXM.SessionManagement.ConditionalSessionIdManager”>
  • In the Sitecore.Forms.Config file which you can find under the App_Config/Include folder, there’s a setting to limit how often can a user submits the form which by default it limit each user to submit 2 form submissions under 1 minute or 100 form submissions under 60 minute. For testing purposes you can for example change the setting to 20 form submissions under 1 minute.
      Server threshold parameters –>
      <setting name=”WFM.ServerThreshold” value=”20/1-100/60″ />

      Session threshold parameters –>
      <setting name=”WFM.SessionThreshold” value=”20/1-100/60″ />

  • If you want to test WFFM in production environment where setting the session to timeout in 2 minutes is not possible, you can clear the browser cookies to force browser session to end SC_ANALYTICS_GLOBAL_COOKIE , SC_ANALYTICS_SESSION_COOKIE and ASP.NET_SessionId. Or you can implement a custom functionality to force browser session end through URL query string such as what has been done here

Sitecore built-in security roles

As the title suggested, gathered from the cookbooks

Client Configuration

Sitecore Limited Content Editor

  • Limits features to provide a simplified Content Editor interface.

Sitecore Limited Page Editor

  • Limits features to provide a simplified Page Editor interface.

Sitecore Minimal Page Editor

  • Removes the ribbon from the Page Editor.


  • Provides access rights to the /sitecore/content branch of the content tree.
  • Member of Sitecore Client Authoring.


  • Provides access rights to the areas of the content tree required when making design changes.
  • Member of Sitecore Client Designing.


  • Provides access rights to the areas of the content tree required during site development and maintenance.
  • Member of Author, Designer, Sitecore Client Developing, Sitecore Client Maintaining, and Sitecore Client Configuring.

To eliminate unnecessary features in the user interface and minimize the potential for users to invoke features by mistake, users should be members of the fewest possible roles. The only exception to this rule is the limited and minimal roles described previously; users should be members of these roles whenever possible. Most users should only be members of the Sitecore Client Authoring role. When users require additional functionality, security administrators can give them additional roles.


Client Authoring 

  • Access to the Marketing Center.

Analytics Reporting

  • Access to the Marketing Center, Engagement Plan Monitor and to the Executive Dashboard.
  • Requires membership of the Client Authoring role.

Analytics Maintaining

  • Access to the Marketing Center, Engagement Plan Designer and Supervisor.
  • Requires membership of the Client Authoring role.

Analytics Testing

  • Access to the Test Lab in the Marketing Center as well as access to the test functionality in the Page Editor and in the Content Editor.
  • Requires membership of the Client Authoring role.
  • Members of this role can create and edit test variations.
  • Users who are not members of this role can switch test variations.
  • Members of the Minimal Page Editor role cannot switch test variations.

Analytics Personalization

  • Access to the personalization functionality in the Page Editor and in the Content Editor.
  • Requires membership of the Client Authoring role.
  • Members of this role can create and edit personalization rules.
  • Users who are not members of this role can switch personalization variations.
  • Members of the Minimal Page Editor role cannot switch personalization variations.

Analytics Content Profiling

  • Access to the content profiling functionality in the Page Editor and in the Content Editor.
  • Requires membership of the Client Authoring role.

All of the analytics roles are members of the Client Users security role


Sitecore Client Form Author

  • The Sitecore Client Form Author role gives the user access to the minimum features of the Web Forms for Marketers module. All the other roles expand the user’s access rights. This role allows the user to:
    • Insert a new form.
    • Edit an existing form.
    • View the Summary report

Sitecore Client Developing

  • The Sitecore Client Developing role allows the user to use the Export to ASCX button in the Form

Analytics Maintaining

  • Use the Analytics page in the Create a New Form wizard
  • Use the Analytics section on the Form Designer ribbon
  • Use the Analytics section on the Content Editor ribbon
  • Use tags

Analytics Reporting

  • View the Dropout report.
  • View the Usability report.
  • View the Save Failures report

Sitecore Marketer Form Author

  • The Sitecore Marketer Form Author role inherits access rights from the following roles:
    • Sitecore Client Form Author
    • Analytics Maintaining
    • Analytics Reporting

Sitecore Client Securing

  • The Sitecore Client Securing role allows the user to:
    • Edit the Create User save action.
    • Edit the Edit Role Membership save action.
    • Edit the Change Password save action

$scw(…).eventTracking javascript error in Sitecore 8 MVC WFFM

If you had an issue where you’re using WFFM in Sitecore 8 where it keeps throwing javascript error about $scw(…).eventTracking you’re missing some file references

For Sitecore 7.5 this files would be the following (Taken from the Sitecore Web Forms for Marketers V2.5 Reference section 3.15.2):

<script src=”~/sitecore/shell/Applications/Modules/Web Forms for Marketers/mvc/jquery-
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for Marketers/mvc/jqueryui-1.8.24.js”></script>
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<script src=”~/sitecore/shell/Applications/Modules/Web Forms for
<link href=”~/sitecore/shell/Themes/Standard/Default/WFM/mvc/Fields/Default.css”
<link href=”~/sitecore/shell/Themes/Standard/Default/WFM/mvc/Fields/Custom.css”
<link href=”~/sitecore/shell/Themes/Standard/Default/WFM/mvc/base/jquery.ui.all.css”

For Sitecore 8 the reference path is a different, see the following:

<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery-1.8.2.min.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery-ui-1.8.24.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery.validate.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery.validate.unobtrusive.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-unobtrusive.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-events-tracking.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-date.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-captcha.js”></script>
<script src=”~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.ajax-form.js”></script>
<link href=”~/sitecore modules/Shell/Web Forms for Marketers/Themes/mvc/Fields/Default.css” rel=”stylesheet”>
<link href=”~/sitecore modules/Shell/Web Forms for Marketers/Themes/mvc/Fields/Colors/Default.css” rel=”stylesheet”>
<link href=”~/sitecore modules/Shell/Web Forms for Marketers/Themes/mvc/Fields/Custom.css” rel=”stylesheet”>
<link href=”~/sitecore modules/Shell/Web Forms for Marketers/Themes/mvc/base/jquery.ui.all.css” rel=”stylesheet”>

Sitecore ECM the remote name could not be resolved: ‘’

Got an error when a user submits a form built using the WFFM. After narrowing it down I found that it has something to do with having to set the save action to send an email.

Here’s the following error:

Exception: System.Net.WebException
Message: The remote name could not be resolved: ‘’
Source: System
at System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6)
at System.Net.PooledStream.Activate(Object owningObject, Boolean async, GeneralAsyncDelegate asyncCallback)
at System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralAsyncDelegate asyncCallback, Int32 creationTimeout)
at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
at System.Net.Mail.SmtpClient.Send(MailMessage message)

If you got an error like that, go to /sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions/Send Email Message and change the parameters field to the correct SMTP details.

For me I need to changed it to the following to make it works


Also I found a useful tool to check email in your local machine, if you don’t need to setup an actual SMTP server and just need to test simple email functionality try using

Sitecore analytics stops tracking

Got a weird issue recently when Sitecore analytics stop tracking page visits on one of our client site. The site is running on Sitecore 7.2 rev 140228 and has been running for a few weeks, looking at the ItemUrls and Visits table the records doesn’t seem to be populated when the site pages was accessed a couple of times even with different browsers.

I quickly ran SQL Server Profiler against the analytics database and try to access a couple of the pages again and definitely see some activities against the analytics database but none of it which inserting data to ItemUrls and Visits table. I tried clearing out all the records in the analytics database, all tables except PageEventDefinitions, TrafficTypes, and VisitorClassifications because those tables have default values in it when we setup a Sitecore fresh install.

Still no avail, I then wondered if the config values for the analytics is set correctly. I access the /sitecore/admin/showconfig.aspx and was able to confirm that the configuration was already right. Trying to pinpoint the issue I was wondering what files are included when we install the analytics feature on Sitecore, opening the zip file I found the following:

  • Sitecore.Analytics.config
  • Sitecore.Analytics.ExcludeRobots.config
  • Sitecore.Analytics.RobotDetection.config
  • Sitecore.Analytics.ldf
  • Sitecore.Analytics.mdf

Wondering if the cause is because one of the following config file I then tried to disable the Sitecore.Analytics.RobotDetection.config file by renaming it to Sitecore.Analytics.RobotDetection.config.disabled (rename the extension to anything other than .config so Sitecore ignores it).

Aha!. The analytics start working again.

In the Sitecore.Analytics.RobotDetection.config file this two line pick my interest
<processor patch:instead="*[@type='Sitecore.Analytics.Pipelines.AcceptChanges.Robots,Sitecore.Analytics']" type ="Sitecore.Analytics.RobotDetection.Pipelines.AcceptChanges.Robots, Sitecore.Analytics.RobotDetection"/>

<processor patch:instead="*[@type='Sitecore.Analytics.Pipelines.InitializeTracker.Robots,Sitecore.Analytics']" type ="Sitecore.Analytics.RobotDetection.Pipelines.InitializeTracker.Robots, Sitecore.Analytics.RobotDetection"/>

It replaces the Robots tracker from the Sitecore.Analytics and use the one from Sitecore.Analytics.RobotDetection dll instead. When I take a look on the Sitecore.Analytics.RobotDetection assemby this is what I found.

public override void Process(AcceptChangesArgs args)
Assert.ArgumentNotNull((object)args, "args");
if (AnalyticsSettings.DisableDatabase)
if (args.Visitor.VisitorClassification < 900 || !AnalyticsSettings.Robots.IgnoreRobots || Switcher<bool, saverobotsenabler="">.CurrentValue)

public override void Process(InitializeTrackerArgs args)
Assert.ArgumentNotNull((object) args, "args");
if (!AnalyticsSettings.Robots.AutoDetect)
if (Tracker.CurrentVisit.VisitorVisitIndex <= 1 && Tracker.CurrentPage.VisitPageIndex <= 1 && args.CanBeRobot)
Tracker.Visitor.SetVisitorClassification(925, 925, true);

On the first visit it will set the visitor classification to 925 which means this visitor is flagged as Bot – Auto Detected which then on the acceptChanges pipeline it will abort the pipeline causing it not to insert any data to the ItemUrls and Visits table.

The issue is on the Sitecore.Analytics.RobotDetection.Pipelines.InitializeTracker.Robots class, it always mark the visitor on first visit as Bot which caused the activity to be ignored by the Sitecore analytics. Compared to what Sitecore.Analytics.Pipelines.AcceptChanges.Robots is doing here
public override void Process(InitializeTrackerArgs args)
Assert.ArgumentNotNull((object) args, "args");
if (!AnalyticsSettings.Robots.AutoDetect)
if (Tracker.CurrentVisit.VisitorVisitIndex <= 1 && Tracker.CurrentPage.VisitPageIndex <= 1)
if (args.CanBeRobot)
Tracker.Visitor.SetVisitorClassification(925, 925, true);
else if (Tracker.CurrentPage.VisitPageIndex == 2 || Tracker.CurrentVisit.VisitorVisitIndex == 2 && Tracker.CurrentPage.VisitPageIndex <= 1)
Tracker.Visitor.SetVisitorClassification(Tracker.Visitor.VisitorClassification == 925 ? 0 : Tracker.Visitor.VisitorClassification, Tracker.Visitor.OverrideVisitorClassification == 925 ? 0 : Tracker.Visitor.OverrideVisitorClassification, true);

on Sitecore.Analytics.Pipelines.AcceptChanges.Robots it will mark the visitor as Bot on the first visit but then on the second visit it will mark the visitor as Unidentified and log the activitiy to ItemUrl and Visits table.


My colleague Cahyadi Hendrawan contacted Sitecore support and confirmed there was a breaking changes in Sitecore 7.2 robot detection logic. The solution was to add



Sitecore – JqueryModalDialogs error when opening popup modal

I got an issue when trying to open a modal popup when logged in to Sitecore

Error when trying to show popup modal dialog

Error when trying to show popup modal dialog

The site has just been setup in IIS, the server is running Windows Server 2008 R2 and it’s using Sitecore 7.2. The strange thing is that there’s another site that’s running under the same Sitecore version and the issue does not happen over there.

I got a clue after opening the ApplicationHost.config file on system32\inetsrv\config and it turns out that on the other site the UrlScan 3.1 was removed from the ISAPI Filters. After i do that the new site runs smoothly as well.

Using powershell to install Sitecore from a zip file until we get a running website

I had a chance to play around with powershell to get Sitecore up and running supplied only with the Sitecore zip file. Starting with a discussion with a colleague of mine about how powershell can register a website in IIS and also have access to Sql Server database i’m curious to actually try it out.

The script basically does the following

  • Get Sitecore CMS and DMS zip file from a specified folder file
  • Extract both zip file into a target folder
  • Structure the folder so that DMS files goes into the right folder
  • Register a new web application pool in IIS
  • Register a new website in IIS
  • Update the host file
  • Attach the database files in Sql Server
  • Start the website
  • Open a browser and if all went ok we’ll have Sitecore displayed

I get to know a few things about powershell as well in doing this, it’s actually pretty powerfull stuff. Feel free to checkout the code in

Sending out Microsoft Search Server failed crawl messages

What i want to do is to build an app that send out an email every time there’s a failed crawl operation when we trigger the crawling operation against a service service application. After reading about it, it seems there are no configuration in the Microsoft Search Server that provide this out of the box.

Instead i found out that you could use the PowerShell to perform administrative task. From getting the search service application of a farm, add it, delete it, and other kind of tasks, read more about the cmdlets available in the documentation.

With this knowledge I’m set to build is a simple script to get the current error message from today’s crawl operation and then send the results through an email. This script will be triggered daily by a task scheduler.

I have no experience on coding on PowerShell before and luckily i found some existing script that i can just tweak a bit to do just what i want.

The PowerShell script that I’ve tweaked.

$ver = $host | select version if ($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = "ReuseThread"} if ( (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null ) { Add-PsSnapin Microsoft.SharePoint.PowerShell } #----CONFIGS $searchServiceName = "just testing" $logFilePath = "c:\temp\searchserverlog.txt" function GetErrorLogs(){ $ssa = Get-SPEnterpriseSearchServiceApplication | Where-Object {$_.Name -eq $searchServiceName} $ssaContent = new-object Microsoft.Office.Server.Search.Administration.Content($ssa) $logViewer = New-Object Microsoft.Office.Server.Search.Administration.Logviewer $ssa $ErrorList = $logViewer.GetAllStatusMessages() | Select ErrorId $crawlLogFilters = New-Object Microsoft.Office.Server.Search.Administration.CrawlLogFilters; $crawlLogFilters.AddFilter([Microsoft.Office.Server.Search.Administration.MessageType]"Error"); $startNum = 0; $errorItems += $logViewer.GetCurrentCrawlLogData($crawlLogFilters, ([ref] $startNum)); WHILE($startNum -ne -1){ $crawlLogFilters.AddFilter("StartAt", $startNum); $startNum = 0; $errorItems += $logViewer.GetCurrentCrawlLogData($crawlLogFilters, ([ref] $startNum)); } return $errorItems } function sendEmail($errorItemsParam){ $currentDate = get-date; $isThereAnyErrorsToday = "false"; $result = "<table>"; foreach($error in $errorItemsParam){ $date = get-date $error.LastTouchStart; if($date.Date -eq $currentDate.Date){ $result += "<tr><td>DisplayUrl</td><td>"+$error.DisplayUrl+"</td></tr>"; $result += "<tr><td>ErrorLevel</td><td>"+$error.ErrorLevel+"</td></tr>"; $result += "<tr><td>ErrorMsg</td><td>"+$error.ErrorMsg+"</td></tr>"; $result += "<tr><td>HResult</td><td>"+$error.HResult+"</td></tr>"; $result += "<tr><td>ErrorDesc</td><td>"+$error.ErrorDesc+"</td></tr>"; $result += "<tr><td>ContentSourceId</td><td>"+$error.ContentSourceId+"</td></tr>"; $result += "<tr><td>LastTouchStart</td><td>"+$error.LastTouchStart+"</td></tr>"; $result += "<tr><td colspan='2'></td></tr>"; $result += "<tr><td colspan='2'></td></tr>"; $isThereAnyErrorsToday = "true"; } } $result += "</table>"; #Write-Host $result $result > $logFilePath #SMTP server name $smtpServer = "" #Creating a Mail object $msg = new-object Net.Mail.MailMessage #Email structure $msg.From = "" $msg.ReplyTo = "" $msg.To.Add("") $msg.Subject = "Search server error logs" $msg.Body = Get-Content $logFilePath $msg.IsBodyHtml = "true"; #Creating SMTP server object $smtp = new-object Net.Mail.SmtpClient($smtpServer) #Sending email if($isThereAnyErrorsToday -eq "true"){ Write-Host "Sending Email" $smtp.Send($msg) } else{ Write-Host "No error today" } } $messageBody = GetErrorLogs sendEmail($messageBody)

This script will be executed by a batch script which in turn is setup to run every day by a Task Scheduler.

powershell -noexit "& "D:\search-error-in-logs.ps1"


The end result would be like this

DisplayUrl ErrorLevel 2 ErrorMsg The URL of the item could not be resolved. The repository might be unavailable, or the crawler proxy settings are not configured. To configure the crawler proxy settings, use Search Administration page. HResult -2147216863 ErrorDesc ContentSourceId 3 LastTouchStart 03/22/2013 00:24:01 DisplayUrl ErrorLevel 2 ErrorMsg The URL of the item could not be resolved. The repository might be unavailable, or the crawler proxy settings are not configured. To configure the crawler proxy settings, use Search Administration page. HResult -2147216863 ErrorDesc ContentSourceId 3 LastTouchStart 03/22/2013 00:23:53 DisplayUrl ErrorLevel 2 ErrorMsg The URL of the item could not be resolved. The repository might be unavailable, or the crawler proxy settings are not configured. To configure the crawler proxy settings, use Search Administration page. HResult -2147216863 ErrorDesc ContentSourceId 3 LastTouchStart 03/22/2013 00:23:53 DisplayUrl ErrorLevel 2 ErrorMsg The URL of the item could not be resolved. The repository might be unavailable, or the crawler proxy settings are not configured. To configure the crawler proxy settings, use Search Administration page. HResult -2147216863 ErrorDesc ContentSourceId 3 LastTouchStart 03/22/2013 00:23:53 DisplayUrl ErrorLevel 2 ErrorMsg The URL of the item could not be resolved. The repository might be unavailable, or the crawler proxy settings are not configured. To configure the crawler proxy settings, use Search Administration page. HResult -2147216863 ErrorDesc ContentSourceId 3 LastTouchStart 03/22/2013 00:23:51