April 2010 - Posts

One thing that is getting a lot of attention in SharePoint 2010, is the use of PowerShell.  It’s too cool and you really have a lot of power (no pun intended) to automate just about anything in SharePoint.  In fact Kyle Kelin (@spkyle) are speaking this weekend about it at SharePoint Saturday Houston (#spshou).  The Microsoft.SharePoint.PowerShell snapin comes with over 500 commands, but you might want to create your own.  Today’s post will show you how to get started.  There are a lot of great posts out there on how to build a regular PowerShell cmdlet, but I wanted to build one that focused specifically on building one for SharePoint. 

Start by creating a new class library project in Visual Studio 2010.  It’s too bad there isn’t a built-in project template, because there are a number of references you must add.  Several of these references don’t show up in the references browser either, so you have to actually specify the path directly from the GAC (or get a copy of it from somewhere).  I’ll include full paths for most things to make it easier for you to add references.

  • System.Management.Automation.dll (C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll)
  • System.Configuration.Install.dll (C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Configuration.Install.dll)
  • Microsoft.SharePoint.dll (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.SharePoint.dll)
  • Microsoft.SharePoint.PowerShell.dll (C:\Windows\assembly\GAC_MSIL\Microsoft.SharePoint.PowerShell\14.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.Powershell.dll)

As I mentioned, some of these you will find in the Add Reference browser, but some you will not.  System.Configuration.Install.dll is only required if you plan on making your assembly a Snapin (we’ll talk about that in a bit).  For some reason, Microsoft.SharePoint.PowerShell.dll is no where to be found in the 14 ISAPI folder, so I included the full path from the GAC.

As you may know, PowerShell commands consist of a verb followed by a noun such as Get-Command.  The full list of available verbs are listed in the SDK or you can take a look at the System.Management.Automation.VerbsCommon class.  You can choose whichever verb makes since followed by the noun of your choice (assuming it isn’t already taken).  For today’s post, we’re going to look at two different verbs: Get and Set.  The methods you override actually depend on which verb you use.  We’ll start with a simple Hello World cmdlet.  The basis of this cmdlet comes from code I first saw at Ignite.  I’m going to create a new class called SPCmdletHelloWorld.cs.

First, start by adding the necessary references.

using System.Management.Automation;

using Microsoft.SharePoint;

using Microsoft.SharePoint.PowerShell;

The class will inherit from a base class depending on the verb we are implementing.  In this case we are implementing a Get verb so it inherits from SPCmdletBase.  The class takes a generic, so that you can specify the return type.  Keep in mind you can return actual objects such as SPWeb.  It doesn’t have to be primitives.  The class declaration also takes a Cmdlet attribute (I really wish they would have called it Commandlet, but whatever).  This tells PowerShell which verb and noun you are implementing.  In our case, we are implementing Get-SPHelloWorld.  Here is what the declaration looks like.

[Cmdlet(VerbsCommon.Get, "SPHelloWorld")]

public class SPCmdletHelloWorld : SPGetCmdletBase<string>

The next step is to override a method to do our work.  The method you override depends on the particular base class you are overriding from.  In this case, we want to override from RetrieveDataObjects which returns an IEnumerable which I assume has to be the same type as we defined on the class.  In this case we are returning some strings.

protected override IEnumerable<string> RetrieveDataObjects()

{

    return new string[] { "Hello World from DotNetMafia.com!", "This is my first commandlet!" };

}

The whole class together looks like this.

using System;

using System.ComponentModel;

using System.Collections.Generic;

using System.Management.Automation;

using Microsoft.SharePoint;

using Microsoft.SharePoint.PowerShell;

 

namespace DotNetMafia.SharePoint.PowerShell

{

    [Cmdlet(VerbsCommon.Get, "SPHelloWorld")]

    public class SPCmdletHelloWorld : SPGetCmdletBase<string>

    {

        protected override IEnumerable<string> RetrieveDataObjects()

        {

            return new string[] { "Hello World from DotNetMafia.com!", "This is my first cmdlet!" };

        }

    }

}

At this point, we should be able to compile our cmdlet, import it, and be able to execute it.  We don’t have a snapin, but we can still register the code to be executed from PowerShell by using Import-Module.  Specify the full path to the assembly to load it.

Import-Module C:\Code\PowerShell\DemoCmdlet\bin\debug\DotNetMafia.PowerShell.DemoCmdlet.dll

With the module loaded we can execute it using the Get verb.

Get-SPHelloWorld

This will give us results that look like this.

PowerShellCmdletHelloWorld

Now, I’m far from a PowerShell expert, so I had to do some research to figure out what the difference between a PowerShell module and a PowerShell Snapin is.  Both allow you to execute code, but how it is executed varies greatly.  From what I gather though, Snapins are the original way of executing code and in PowerShell 2, modules will be the new way going forward.  This post gives more information on it if you are curious.  There are a few extra steps involved to create a Snapin, but it’s worth seeing, so I’m going to cover them quickly.  I do know that Snapins require admin privileges since you have to put them in the GAC.

First, we need to create a class and inherit from System.Management.Automation.PSSnapin.  I don’t believe it matters what this class is named.  It simply appears to handle the installer logic when you later install the Snappin with GacUtil / InstallUtil (much like a windows service).  In the class we simply override a couple common properties to provide more information about the Snapin.  Here’s what mine looks like.

using System;

using System.ComponentModel;

using System.Management.Automation;

using Microsoft.SharePoint;

using Microsoft.SharePoint.PowerShell;

 

namespace DotNetMafia.PowerShell.DemoCmdlet

{

    [RunInstaller(true)]

    public class DemoPowerShellSnapIn : PSSnapIn

    {

        public override string Name

        {

            get { return "DotNetMafia.PowerShell.DemoCmdlet"; }

        }

 

        public override string Vendor

        {

            get { return "DotNetMafia.com";  }

        }

 

        public override string Description

        {

            get { return "DotNetMafia PowerShell Demo Cmdlet"; }

        }

    }

}

Another file that we may (or may not) have to create is the .psc1 file.  This has the same file prefix as your assembly.  I’m not 100% sure you have to create this (but I have seen it in other sample code), so I’ll show you it just in case.  I do know that you can auto-generate this file using a PowerShell command.

<PSConsoleFile ConsoleSchemaVersion="1.0">

  <PSVersion>1.0</PSVersion>

  <PSSnapIns>

    <PSSnapIn Name="DotNetMafia.PowerShell.DemoCmdlet" />

  </PSSnapIns>

</PSConsoleFile>

The last thing I do is mainly for convenience.  I create a batch file to install my Snapin every time I compile.

@SET GACUTIL="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\gacutil.exe"

@SET INSTALLUTIL="C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe"

 

%GACUTIL% -if DotNetMafia.PowerShell.DemoCmdlet.dll

%INSTALLUTIL% DotNetMafia.PowerShell.DemoCmdlet.dll

When you compile, you should now see the installer run which looks something like this.

Running a transacted installation.
 
  Beginning the Install phase of the installation.
  See the contents of the log file for the C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.dll assembly's progress.
  The file is located at C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.InstallLog.
  Installing assembly 'C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.dll'.
  Affected parameters are:
     assemblypath = C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.dll
     logfile = C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.InstallLog
     logtoconsole =
 
  The Install phase completed successfully, and the Commit phase is beginning.
  See the contents of the log file for the C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.dll assembly's progress.
  The file is located at C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.InstallLog.
  Committing assembly 'C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.dll'.
  Affected parameters are:
     assemblypath = C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.dll
     logfile = C:\Code\PowerShell\DemoCommandlet\bin\Debug\DotNetMafia.PowerShell.DemoCmdlet.InstallLog
     logtoconsole =
 
  The Commit phase completed successfully.
 
  The transacted install has completed.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

If you remember from my first PowerShell post, we register a Snapin with the Add-PSSnapin command.  We can then use Get-Command to inspect which commands are available in the Snappin.  Executing the comamnds is just the same as with the module.  Here is what it looks like.

PowerShellSnapin

You might notice I have two commands listed there.  You can include multiple commands inside one assembly.  Let’s take a look at the second command.  This command actually makes changes inside SharePoint.  It’s a simple command that takes a string and a URL and changes the site title.  This time, we inherit from SPSetCmdletBase<>.  We can treat public fields in our class as command line parameters by using the Parameter attribute.  The position sets the order of the parameters and then you can specify whether they are required or not as well as other options.

[Parameter(Position=0, Mandatory=true)]

public string title;

 

[Parameter(Position=1, Mandatory=true)]

public string url;

Instead of overriding RetrieveDataObjects, we override UpdateDataObject instead.  Then I just use the URL parameter to get an SPWeb object and then update the title. Here’s what the entire class looks like.

using System;

using System.ComponentModel;

using System.Collections.Generic;

using System.Management.Automation;

using Microsoft.SharePoint;

using Microsoft.SharePoint.Administration;

using Microsoft.SharePoint.PowerShell;

 

namespace DotNetMafia.PowerShell.DemoCmdlet

{

    [Cmdlet(VerbsCommon.Set, "SPTitle"), SPCmdlet(RequireUserFarmAdmin = true)]

    public class SPCmdletSetTitle : SPSetCmdletBase<SPWeb>

    {

        [Parameter(Position=0, Mandatory=true)]

        public string title;

 

        [Parameter(Position=1, Mandatory=true)]

        public string url;

 

        protected override void UpdateDataObject()

        {

            using (SPSite siteCollection = new SPSite(url))

            {

                using (SPWeb site = siteCollection.OpenWeb())

                {

                    site.Title = title;

                    site.Update();

                }

            }

        }

    }

}

It looks like this when we execute it.  I’m prompted for parameters since they are mandatory.

PowerShellCmdletSPTitle

When we look at the site now, we can see the changed title.

PowerShellSiteTitleChanged

Hopefully, this is enough to get you started with PowerShell cmdlets.  There is so much more you can do here than what I have mentioned, but this will get you started with two command verbs: Get and Set.  I’ve also attached the code that I have shown to this post.  Enjoy.

I was working on updating my Search demo for #spshou and my BCS search results were really ugly.  I didn’t have a default action specified on my search results, nor did I have a profile page, so instead the search results would give me the BDC protocol URL which is not usable by an end user. 

BCSSearchResults

In MOSS 2007, if you did not create a default action, it would automatically create a profile page for you.  In SharePoint 2010, this is not the case.  It’s pretty easy but there are a few steps involved.

Start by opening SharePoint Designer and open your external content type in question.  In the top right, you will find the Create Profile Page button. 

BCSSharePointDesignerNewProfilePageButton

Give it a click.  However, if you haven’t configured a profile host URL, you will get the following error.  Chances are you haven’t configured one of these yet.

BCSSharePointDesignerProfilePageError

Unable to provision profile page because the profile host URL was not specified.

After doing a search, I found only one usable result on the Internet on MSDN forums.  It had the answer, but it wasn’t clear to me at first.  It said to use the Configure button in the ribbon.  However, I was looking in SPD, and in fact its in the Service Application instead as you can see below.

BCSServiceApplicationConfigureButton

Select the application you want to edit and then you can click Configure.  This brings up the popup shown below which prompts you for a URL of the site that to keep you profile pages in.  I like this since you can configure these at a per application definition level now instead of one location for every entity on the SSP.

BCSConfigureProfileSite

I decided that I wanted my profile pages in a specific subsite, so I went ahead and created a new one.

BCSProfileNewProfileSite

After I finished configuring my site and setting up the Profile Page Host, I was able to go back to SPD and click the button.  This pops up a progress bar, but it doesn’t really give you any visual indication that anything is done.  I then went back to my content sources and recrawled my BCS content source.  When it finished, I executed a new search, and now I get actual usable URLs in my search results.

BCSSearchResultsProfilePage

As you can see it generated kind of a long URL with _bdc in it.  I believe the http and sp2010 come from the namespace specified in SharePoint Designer.  Finally it names a page after the entity itself.  So far, I’m not sure if any of the page name stuff is configurable or not, so I need to look into that.  Once you click on the page, you get a simple profile page to display the results.

BCSProfilePageComplete

It’s simple, but it has all the pertinent information from the underlying database table.  It beats what I had before.  I think a custom default action can be specified just like in MOSS 2007, but I get the feeling you have to edit the application definition XML manually to make it happen.  I’m still looking into it.  Anyhow, I hope this helps, the next time you try to use the BCS.

When I was mapping some managed properties from one of my Content Sources using the BCS, I noticed that the crawled properties were named slightly different in SharePoint 2010.  I thought this was worth a quick note, so here we are.  In MOSS 2007, each crawled property was prefixed by the application definition name, followed by the entity name.  Now (as of Beta 2) everything seems to be prefixed by Read ListElement.  Here is what some of my properties look like.

EnterpriseSearchBCSCrawledProperties

Notice it actually shows a space now instead of x0020.  The naming convention appears to be static here so unfortunately you don’t really have a way of telling what entity each item is coming from.  This might be a good thing though.  Since before, if you had a field with the same name in 10 different entities, you had to map each one to the managed property.  The prefix appears to always be the same too (even if you change the name of the operation).  Read List is the name of the operation used to iterate a BCS list now as you can see in SharePoint Designer.

BCSSharePointDesignerOperations

The name can be changed in SPD, however it appears that the prefix never changes as far as crawled properties go. Anyhow, I just wanted to quickly share this change I noticed today.  I’ll be posting more on the BCS and Search soon.

We had a great turnout last night for my talk on How the SharePoint 2010 Business Connectivity Services will change your life.  The talk went quite well despite the long wait times in SharePoint Designer 2010. :-)  I really enjoyed giving this talk because it truly wows a lot of people.  When they see how you can bring data in from a backend system, edit it in SharePoint and then sync it with SharePoint Workspace or edit it directly from Microsoft Outlook, they are truly impressed.  I can’t wait to give this talk again on a release build.  If you want to see my awesome slide deck, I’ve posted it on SlideShare.  Thanks for coming.

Follow me on twitter.

I’m excited to bring a SharePoint 2010 talk to the Tulsa SharePoint Interest Group this Monday (4/12).  Here is a brief summary.

How many hours have your wasted building simple ASP.NET applications to do nothing more than simple CRUD operations against a database?  Many tools have made this easier, but now it's so easy, you'll be up and running in minutes.  This session will show you hot easy it is to get started integrating external data from your line of business systems in SharePoint 2010.  You will learn how to register an external content type using SharePoint Designer based upon a database table or web service and then build an external list.  With external lists, you will see how you can perform CRUD operations on your line of business directly from SharePoint without ever having to do manual configuration in XML files.  Finally, we will walk through how to create custom edit forms for your list using InfoPath 2010.

For more information or to register, click here.

Also, Tulsa SharePoint Interest Group is now on twitter @TulsaSPIG.

So your organization has decided to implement SharePoint and you finally got your VP to sign off on approval to fill that SharePoint position you so desperately need filled.  With IT positions in the past, your first thought might be to contact HR or your favorite recruiter and see who they can find.  This might work in the SharePoint world, but there is no guarantee that you will get someone good.  You see SharePoint is different.  It’s a complex beast and it needs to be handled with care.  The more things you do wrong in the beginning will just make them harder to fix later. 

Just because someone has SharePoint on their resume, doesn’t mean he or she knows how to administer it or develop for it.  Chances are the recruiter just told the person to add some bullet points about SharePoint to the resume after the first copy was received.   Let’s face it, just because someone has uploaded a file to a document library before doesn’t make them a SharePoint administrator.  If that was the case, then you should just hire your Vice President of Sales to take over all of your SharePoint admin work.  Most recruiters are not technical people.  They are sales people.  More than likely, they really don’t know who knows SharePoint and who doesn’t.

So who does know who is good at SharePoint?

The SharePoint community does.  SharePoint is backed by a huge community of fans.  I would venture to say that SharePoint has the largest community support of all Microsoft products (although I have no way to prove that :) ).  These people live, breathe, worship, and curse SharePoint all day and all night.  This great group of people talk about SharePoint all the time. They attend, speak, or even organize community organized events like SharePoint Saturdays.  You want an admin or developer that is heavily involved in the community.  They don’t have to be a public speaker, but you want someone involved.  This could be by attending conferences, user groups, blogging, or answering questions in the MSDN forums.  If they are a public speaker, that is great too.  This means, you can probably go out and look at the slides, code samples, and maybe even videos and see what that person knows.

How do I engage the community about my open position?

Simple answer. Twitter.  Now calm down. I know your company blocked the site months ago because it was one of those evil dreaded “Social Media” sites.  This isn’t Facebook though.  Most people that use Facebook, don’t have a clue about Twitter.  They just don’t get it.  Twitter is the backbone to the SharePoint Community.  It’s not a place where we waste time harvesting our virtual farms.   Asking a SharePoint developer to work without twitter is like asking them to work with one hand tied behind their back.  I’m not the only one that thinks so.  Why?  This is how we communicate with one another.  Have some strange error on your SharePoint server and you don’t know how to resolve it?  Ask twitter, chances are you’ll have a response back in minutes.  Need instructions on how to write CAML to deploy a file via feature?  Ask twitter.  There is value there, you just have to embrace it. 

We have Twitter blocked because we don’t want our company secrets leaked…

Chances are your company secrets aren’t going to be leaked via twitter.  I don’t care what sites you block or how much you lock down the computer that your employees are on.  If you have someone that wants to take information out of your company and give it to a competitor, there is not much to stop them.  Or did you forget that they can print out that spreadsheet of new prospects using the printer on their desk?   If you’re worried about productivity loss, there might be some, but its negligible.  If your employees can’t check Twitter or Facebook using their computer, they are just going to pull out their cell phone and check it there.  This leads to more productivity loss since using a cell phone is not as fast as using a computer. 

I’m new to twitter…

Before you get started finding someone on twitter, you will need to post your job information somewhere.  This can be on your corporate site or wherever.  You just need to have something to link to.  If you or your company is new to twitter, you can handle this in a couple of different ways.  You probably want to start following some known SharePoint people.  If you don’t know any SharePoint people, then I recommend doing a search on the #SharePoint hash tag.  This feed will contain a slew of people that are all talking about SharePoint.  Follow these people and they will probably follow you back.  Following people isn’t necessarily required though.  If you tweet about your job and include the #SharePoint hashtag, people searching that hash tag will see it and probably help you spread the word by retweeting.  Especially if the job opportunity is a good one.  If you’re not sure what to post try something like this.

<Company Name> is looking for a SharePoint Architect in Dallas, TX.  Great Company.  Great Benefits.  <link to job listing> #SharePoint”

I assure you if you post something like that, you will get some great candidates.  Give it a try for your next SharePoint position.  Once you identify some candidates, you can quickly see how involved the person is in the community. 

Is this candidate the right one?

Good question.  If the person you are looking to hire, can’t be found on twitter, you probably don’t want them.  Twitter is the primary means of communication within the community.  If he or she is not on there, then they aren’t very well connected.  The ideal candidate has participated (i.e.: attending, speaking, volunteering, or organizing) in at least one SharePoint Saturday.  These are free and there is one happening just about every weekend so chances are there has been one close to you (if not in your own city).  Another good measure is to look at their participation on MSDN forums.  Ask the candidate how many points or ribbons they have.  If the candidate has a few thousand points or a couple of ribbons, this means he or she is helping people in the real world solve their SharePoint issues. 

Another thing to check is the candidates blog.  Hopefully, you can find it on the candidates resume, via the twitter profile, or just by doing an Internet search.  If the candidate regularly posts about their experiences with SharePoint or how to solve real world issues, this is a good thing.  This is a great way to get an idea of a candidates knowledge outside of the resume and interview process.

At this point, you might have noticed I left out certification.  Although, certification is not a bad thing, it doesn’t necessarily prove anything either.  Honestly, from the two tests I have taken, I have found that they are really just too easy.  I’ve met people that have never done a SharePoint project and have passed the MOSS Configuring test.  I do think this will improve with the SharePoint 2010 tests, but its still too early to tell.  Certifications are still good but don’t let them be too much of a defining criteria in selecting candidates.  Now, if they have a SharePoint MCM, that’s another story.  That’s definitely an achievement.

If you take this approach to filling your SharePoint position, there should be no reason to ever pay a commission to a recruiter to find a SharePoint person.  Now, recruiters, I mean no disrespect here, but this type of position, I feel is truly different.  As a recruiter, if you are trying to fill a SharePoint position, there is no reason why you can’t look for people via twitter of course as well.  These are the types of questions you should be asking your potential SharePoint candidate.  If you have a candidate that is active in the community like I talked about above, you stand a greater chance of getting that person in the door.

I don’t write non-technical articles very often, but hopefully someone find this useful.  Am I right on any of this?  I do know of plenty of people that have found their next position via twitter, so I really think it’s viable.  This post of course is pretty much all opinion so if you agree or disagree, leave a comment. :-)

with 8 comment(s)
Filed under:

I was doing some SharePoint mentoring a while back and I noticed that some developers don’t know about a couple handy items found in various context menus that that I use on a daily basis.  Specifically I’m talking about a few things in the context menu that give you the path to the file or open the folder that the file is in.  These can be useful when you are ghetto deploying files or you simply want to jump to the file system to grab your .wsp file.  Honestly these menu items have been around for a long time, but I hadn’t noticed them until a while back.  If you already know about them, you can stop reading here. :-)

The first menu I want to talk about is the context menu you get by right clicking on the tab of any open file.  This is from Visual Studio 2010, but its there in 2008 as well.  I’m not sure about 2005, but if you are still using Visual Studio 2005, you should be ashamed of yourself.

VisualStudioContextMenuFile

The two menu items of interest here are Copy Full Path and Open Containing Folder.  As expected, Copy Full Path puts the full path to the file in the clipboard.  This is great when you have a file open in Visual Studio and you need to upload it via browser File Upload control.  You can just paste the path right in and you’re good to go.  I use this when I’m uploading BDC application definitions a lot.  The Open Containing Folder is useful any time you need to copy the file in your project from one place to another.

If you don’t have a file open, you can make use of another item on the context menu from the Solution Explorer.

VisualStudioContextMenuFile2

This opens the folder the file is in with windows explorer.

Directory structures for source code can be huge these days.  Lots of nested folders and it takes time to click through them.   I mention these topics today because I’ve watched developers open a new instance of windows explorer and browse through the folder structure every time.  Anyhow, maybe you already use these menu options.  I thought they were useful and worth a quick mention.

Lots of things have changed in Enterprise Search and the CoreResultsWebPart is no exception.  Of course, I’ve already mentioned that you can override certain methods now to affect how queries execute.  A number of options have moved around and a few new ones have shown up.  If you remember MOSS 2007, the properties looked something like this.

EnterpriseSearch2007Properties

Most of the options you have used before are still there, it’s just a matter of finding them.  The groups are now Location Properties, Display Properties, Results Query Options, and More Results Link Options.

EnterpriseSearchCRWPProperties1

The first thing to note is the Location Properties.  If you ever took a look at Federated Search, this might look familiar to you.  All web parts now use the Location to get default values.  This allows the CRWP to display local search results, people, FAST, or federated locations as well.  Take a look at the options.

EnterpriseSearchCRWPLocations

Ok, yours probably won’t have the DotNetMafia.com Search Results.  I added that for my demo on Enterprise Search I gave last week.  Also note that the Scope property has been moved here instead of being buried under Miscellaneous.

Staying with the Location theme here, let’s take a look inside Display Properties.

EnterpriseSearchCRWPProperties2

Notice that the Fetched Properties and XSL Editor are grayed out?  This is because the Use Location Visualization checkbox is set.  This tells the CRWP to use the columns and XSL defined at the federated location level.  If you we go to the Search Service Application and look at the Local Search Results Federated Location, we will see that they added a new section for the CRWP.

EnterpriseSearchFederatedLocationCRWP

What’s cool about this is that you can define a consistent look and feel for search results for all search centers on your farm.  Of course, if you don’t want to use the location’s defined visualization, you can uncheck the Use Location Visualization checkbox in the CRWP and define your own.

Let’s take a look at some of the other options.  Under Display Properties, you can also set the sort order (sorry only Relevance and Modified Date are still supported unless you use FAST).  There are also new options to limit the number of characters in the URL as well as in the summary.

The last section to mention is Results Query Options.  A new dropdown is available to override the Query Language.  The Cross-Web Part query ID has been moved here.  You can also still specify the Fixed Keyword Query here and you can make use of the Append Text To Query option that I have mentioned in a previous post.  Remove Duplicates, Search Stemming, and Ignore Noise Words all got moved here as well.

CoreResultsWebPartAppendQuery

This only configures the configuration changes of course.  The Web Part itself underwent a ton of changes to make it support overrides, FAST Search, Wildcards, and more.