Oct 122011

Running remote Powershell scripts for SharePoint

 

I’ve been playing around with Powershell the last week and thought I’d post some of my trickier findings:

 

Remoting with powershell

 

With remoting you can script installations or configurations that should be done on multiple farms/servers without having to login to each farm and run the script with it’s variables. Now you can just build 1 big script with variables and run each part of the script with a remote powershell session opened with the correct credentials.

 

The code below calls some functions to start a new remote session with fixed name, load variable / functions file into the session to be used later, run your code using the variables and functions, end session.

 

StartRemoting $AUTH_Servername $AUTH_ServerUser $AUTH_ServerUserPassword
            $s = Get-PSSession -Name "RemoteSP2010Script"
            Invoke-Command -Session $s -ScriptBlock {
            LoadSharePointCmdlets
                                                #YOUR CODE
            }
            StopRemoting $AUTH_Servername

 

function LoadSharePointCmdlets()
{

Write-Host "- Loading SharePoint cmdlets" -foregroundcolor "Green"
Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
}

function StartRemoting($Server, $Username, $Password)
{
    #Build credentials from variables
    if($Username -eq $NULL)
    {
        $Credentials = $NULL
    }
    else
    {
        $Credentials = New-Object -TypeName System.Management.Automation.PSCredential 
                                                        -argumentlist $Username , $Password 
    }

    #enable remoting
    enable-PSRemoting -confirm:$false
    
    #increase memory limit for remote shell
    Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 1000 

    #Disconnects the client remote desktop
    #Enable-WSManCredSSP -Role client -DelegateComputer $Server -Force
    
    Write-Host "Starting new remote session to" $Server -foregroundcolor "Green"
       if ($Credentials -eq $NULL)  
      {  
            $s = new-psSession -ComputerName $Server -Name "RemoteSP2010Script"
      } 
      else
      {
           $s = new-psSession -ComputerName $Server -Authentication CredSSP
                                       –Credential $Credentials -Name "RemoteSP2010Script"
      }
    
    #Load Variables & functions into remote session
    Write-Host "Loading variables and functions into remote session"  -foregroundcolor "Green"
    
    Invoke-Command -Session $s -FilePath $VariableFileLocation -ErrorAction SilentlyContinue
    Invoke-Command -Session $s -FilePath $FunctionsFileLocation -ErrorAction SilentlyContinue
}

function StopRemoting($Server)
{
    Write-Host "Closing remote session to" $Server -foregroundcolor "Green"
    Remove-PSSession -ComputerName $Server
}
Published: 10/12/2011  8:38 PM | 0  Comments | 0  Links to this post

Oct 122011

SharePoint 2010 web applications with host header eventID 4625 – 0xc000006d

I made a new web application today on my SharePoint 2010 development machine through Central Administration and entered a Fully qualified domain name FQDN as url like http://company.intranet and added the mapping in my host file.

 

When trying to connect to my new web application / root site collection I got a pop-up windows asking my login 3 times after which I just got a blank screen.

I ping’ed the url and it did return my 127.0.0.1 IP so I was sure the address lookup was correct.

 

In the event viewer I could see an error with eventID 4625 and error 0xc000006d.

 

Turns out this is quite normal and by design, it’s a safety precaution in IIS. I found the solution on this blogpost.

 

When you use integrated authentication and you have the website as a local IIS site, then you will only be able to access the website using the machine name (http://codejourney). You will not be able to access it using a FQDN.

 

How to disable loopback check for local IIS websites:

 

There are 2 ways to get past this annoyance.


Both solutions require registry editing, so remember to create a backup first.
Solution 1 (Preferred): Specify which host names that does not cause loopback check.

1: Open up the registry editor by typing regedit under Run.
2: Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
3: Right-click MSV1_0 and click New and choose to make it a Multi-String Value.
4: Enter BackConnectionHostNames as name for the entry, and double-click it to modify it.
5: Type the hostnames you need to use (code-journey.com for instance).
6: Restart IISAdmin Service (“Start” -> “Administrative Tools” -> “Services”)

Solution 2 (Not recommended):
1: Open up the registry editor by typing regedit under Run.
2: Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
3: Right-click Lsa and click New and choose to make it a DWORD Value.
4: Enter DisableLoopbackCheck as name for the entry, and double-click it to modify it.
5: Set the value to 1 and click OK

Published: 10/12/2011  8:26 PM | 0  Comments | 0  Links to this post

Apr 072011

My first CodePlex project: Timerjob dynamic settings – creation - deletion in Central Administration.

 

Today I created my first CodePlex project. It’s a fun SharePoint (2007 so far) project for managing timerjobs.

 

- You can add custom timerjob definitions to a namespace in the project and whatever public property’s you want. There is one example of a dummy definition with dummyProperty.

- The project creates 2 application pages available from central administration through the operations tab with the rest of the timerjob settings.

 

 

 

TVR timerjob creation page

 

First page is for creating instances of a timerjob definitions from your project. A dropdown list will display all available timerjob definitions in your project.

When you select one the page will dynamically show all public variables of the definition in the page with a label and textbox for each.

You can choose a name and schedule for the instance, and set property’s (that are saved in the SPPropertybag of the Central Admin site starting with the name of your instance + property name).

 

 

TVR timerjob settings page

 

This page shows you a dropdown list of all (custom) timerjob instances running on the Central Admin web application. If you’ve created the instance using the first page then it will definitely be displayed here.

 

You have the option to set a new schedule for the instance.

The page dynamically loads all available property’s used by the timerjob instance and shows the values in textboxes so you can edit them.

 

There are also buttons to delete the current timerjob instance or run it now! (Which I desperately miss in SharePoint 2007)

 

 

You can find more info and the source code + wsp package at CodePlex.

http://tvrtimerjobsettings.codeplex.com/

 

Please feel free to comment as it’s a first version. Also if you find it a useful tool or how you’d go about things in another ways.

Published: 4/7/2011  9:21 PM | 0  Comments | 0  Links to this post

Mar 072011

SharePoint Guidance 2010

 

Microsoft patterns & best practices for SharePoint 2010

I found this SharePoint 2010 “framework” on codeplex which has been created by several MVP’s. It contains several patterns & best practices which help you best take advantage of the new capability’s of SharePoint 2010.

The website is http://spg.codeplex.com/. Here you can find a large pdf e-book which explains all of the functionality the framework provides + some hands on labs and examples how to implement this into your projects.

At first it looks like a very high level framework but I think it will definitely give some added value to your SharePoint 2010 projects!

An example for this is the application setting manager:

The Application Setting Manager is a set of utility classes that you can use to store and retrieve configuration settings for your SharePoint applications. The Application Setting Manager provides a uniform, type-safe approach for managing configuration settings at the following levels of the SharePoint hierarchy.

 

Farm (SPFarm class)

Web application (SPWebApplication class)

Site collection (SPSite class)

Site (SPWeb class)

 

You can use the Application Setting Manager to store simple types, such as integers or strings, as well as more complex types that can be serialized to XML. The Application Setting Manager manages the serialization and deserialization of data types to and from XML.

 

The Application Setting Manager provides a hierarchical model for the storage and retrieval of configuration settings. This enables you to create an application setting at a broad scope (such as the farm level) and override that setting at a narrower scope (such as the site level). When you retrieve a setting, using a key string, the Application Setting Manager will first look for that key at the site (SPWeb) level of the current execution context.

 

If the configuration key is not found, the Application Setting Manager will look for the configuration setting at progressively broader scope, up to and including the farm level. For example, you could use the following code to locate a configuration setting of type DateTime, without knowing the level in the SharePoint hierarchy at which the setting is stored.

 

IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent();

var config = serviceLocator.GetInstance();

DateTime timeApproved;

if (config.ContainsKey("approvedTime"))

{

timeApproved = config.GetByKey("approvedTime");

}

As illustrated by the code example, you are encouraged to use the SharePoint Service Locator to retrieve and instantiate instances of the interfaces provided by the Application Setting Manager.

 

Gr

Tom

Published: 3/7/2011  1:05 PM | 0  Comments | 0  Links to this post

Jan 272011

TechDays 2011 – Antwerp - Belgium

I’ll be attending my first Microsoft TechDays (Main Conference Only) April 26th and 27th, 2011!

 

I’m already looking forward to it and hope to hear a lot of interesting topics and see some good presentations about things like Visual Studio 2010, Windows Phone 7, Internet Explorer 9, HTML5, Silverlight 4, Lync 2010, Windows Azure, Exchange 2010, etc

 

For those of you that are coming too: C U @ TechDays!

 

Gr

Tom

Published: 1/27/2011  8:33 PM | 0  Comments | 0  Links to this post

Jan 272011

MOSS 2007–WSS 3.0 AspMenu

The AspMenu used by MOSS 2007 and wss 3.0 is based on the .Net 2.0 AspMenu control but has some enhancements built in. The problem is that apparently the SharePoint team sealed the class so you can’t extend the control for yourself.

What they did now is post the sourcecode for their enhanced mossmenu online here. You can just add it as a usercontrol to your masterpage and replace the Sharepoint:AspMenu tag by your custom control, which you can then extend even further.

 

I used this myself because I wanted to change the logic which menuItem is selected in a certain project. My first goal was to have multiple selected items in my menu but apparently this isn’t allowed by the control. Only 1 menuItem can be set selected = true.

 

What I did then was have the parentItem of my currentItem selected in my customMenu:

 

// if no menu item is presently selected, we need to work our way up from the current
              // node until we can find a node in the menu item dictionary
              while (selectedMenuItem == null && currentNode != null)
              {
                  this.menuItemDictionary.TryGetValue(currentNode.Url, out selectedMenuItem);
                  // if we found an item to select, go ahead and select (highlight) it
                  if (selectedMenuItem != null && selectedMenuItem.Selectable)
                  {
                      selectedMenuItem.Selected = true;
                  }
                  currentNode = currentNode.ParentNode;
              }

              if (this.selectStaticItemsOnly)
              {
                  // only static items may be selected, keep moving up until we find an item
                  // that falls within the static range
                  while (selectedMenuItem != null && selectedMenuItem.Depth >= this.StaticDisplayLevels)
                  {
                      selectedMenuItem = selectedMenuItem.Parent;
                      // if we found an item to select, go ahead and select (highlight) it
                      if (selectedMenuItem != null && selectedMenuItem.Selectable)
                      {
                          selectedMenuItem.Selected = true;
                      }
                  }

               
              }
          }

After this I could highlight the current node (of which I know the url) in javascript:

 

function ChangeClassSelectedNodes() {

//Select all links with a href att

$('a[href]').each(function(idx, item) {

//Get the current url

var url = window.location.href.toUpperCase();

//Get each items href in upperCase

var href = item.href.toUpperCase();

//If our current Url contains the items href then change it's class to your SelectedClass

if (url == href) {

item.parentNode.parentNode.className = 'TopMenuSelectedLevel1';

}

});

 

So after this I’d have my current node selected in my Dynamic flyout menu’s en the highest level parentNode selected in my static menu level.

 

Gr

Published: 1/27/2011  8:21 PM | 0  Comments | 0  Links to this post

Jan 272011

PublishingpageImage: Using field value controls and edit mode panels to tweak your page rendering

 

When using a publishingpageImage in your pagelayout it displays a border of 1px at the side of your image. This is especially annoying when you want to display a second image next to it, and you can’t get it aligned perfectly.

 

Before you drive yourself nuts for hours like I did to find out where that pixel comes from look at the following post from ECM Team.

 

It shows that this pixel is caused by the “editing” field of the PublishingPageImage and you can avoid this by using the EditModePanel. This way you add it twice to your page, once where you want to display it (without the pixel!) and once where you want it to appear when editing the page.

 

 

 

Gr

Tom

Published: 1/27/2011  7:13 PM | 0  Comments | 0  Links to this post

Dec 032010

MOSS 2007 People search influenced by synonym list by user language and setting the rowlimit on a query greater than 50.

This post is an addition to my previous post about SharePoint people search.

While building a custom “CoreResultsWebPart” we noticed that some people were not being returned in our search results by the default search.

 

1) But when we searched it with our custom code it did return results.

2) When a french speaking collegue of mine searched using the same webpart he did get the result, but only when he logged into the machine, not just by signing into my IE Sharepoint.

 

When going to the SharePoint logs I found that the query did the following when I searched for “Leemans”:

 

0x231c0031

Type="Synonym">10x00006c00650065, lee

PID="0x7fff7fff" len="13">0x00006c6d0061006e, leeman

len="19">0x00006c6d0061006e006e0065006e, leemannen

len="15">0x00006c6d0061006e0073, leemans1

Count="3">0x00006d0061006e, man

len="13">0x00006d0061006e006e0065006e, mannen0x00006d0061006e0073,

mans

Type="Unknown0x16777206">... 
So the query automatically (also for out of the box Sharepoint people search!) used synonyms to change my queryterms.

 

After some Reflector work on the “SearchResultHiddenObject” class I found the following:

 

try
                {
                    if (!string.IsNullOrEmpty(this._QueryLanguage))
                    {
                        myRequest.Culture = new CultureInfo(this._QueryLanguage);
                    }
                    else if ((this.thisPage.Request.UserLanguages != null) &&

(this.thisPage.Request.UserLanguages.Length > 0))
                    {
                        myRequest.Culture = new CultureInfo(this.thisPage.Request.UserLanguages[0]);
                    }
                }

 

Which means if the param _QueryLanguage isn’t filled in, it used the users language which explains why my french speaking collegue did get results. The french synonym list wasn’t creating issue’s, nor was the english one, just dutch.

 

By adding the following code to my already custom webpart I could set the parameter and garanty that each user use the same, english synonym list.

+ I added some code so the maximum returned results by a query isn’t limited to 50.

public class xxxwebpart: CoreResultsWebPart

{

....

protected override void SetPropertiesOnHiddenObject()

{

base.SetPropertiesOnHiddenObject();

 

// Get Reflection info

object srho = this.GetType().InvokeMember("srho", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic, null, this, new object[] { });

Type type = srho.GetType();

 

//Set RowLimit

type.InvokeMember("_ResultsRequested", BindingFlags.SetField | BindingFlags.Instance | BindingFlags.NonPublic, null, srho, new object[] { ((short)1000) });

 

//Set Query Culture to en-GB to use this synonym list which causes no problems

type.InvokeMember("QueryLanguage", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.Public, null, srho, new object[] { "en-GB" });

 

// Allow the query to be reissued

type.InvokeMember("ForceRerun", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, srho, new object[] { });

}

 

Seeing as the dutch synonym list was not changed but default, I think we can assume all the out of the box people searches for Dutch users will sometimes give no results because of the synonym use…

 

As a quick fix for users that don’t use a custom CoreSearchResults webpart I’ve created a simple webpart called SearchQueryOptionsWebPart that does 2 things:

 

- Sets the culture for the query so you can determine per page which Culture (read which synonymlist) should be used by all users.

- Sets the rowLimit for the query to return. I’ve noticed that a lot of people are also looking for an easy way to increase this above the hard limit of 50.

 

You can find the sourcecode here.

 

Just install the wsp, activate the site collection feature “MOSS2007 Search Query Options WebPart (SQOW) ” and add the webpart to any search result page where you want to set the options.

The default for the options are “en-GB” and 1000 (rowlimit) but you can change these easily in the webpart properties.

Gr

Tom

Published: 12/3/2010  11:28 AM | 0  Comments | 0  Links to this post

Dec 032010

MOSS 2007 People wildcard search webpart and refine your results.

I’ve been searching for a good way to use wildcard search in combination with people search (SharePoint User Profiles) and have found a few but not 100% what I was looking for.

 

My colleague Steven has found a solution for wildcard search which is pretty much the same as the Codeplex solution and DotNetMaffia solution for this problem.

 

My problem was that these solutions are designed for wildcard content search and not specifically for people search. Normally you’d perform a people search in SharePoint by using the “People Search Core Resuls webpart” which includes some nice people specific features such as:

 

- Refine your search (by example refine by job title)

- Sort by social distance

- …

 

Now all the wildcard search solutions I’ve come across don’t include these features because they all extend the “ CoreResultsWebPart “ instead of the “ PeopleCoreResultsWebpart “ and there is a very good reason for this, being that that class is sealed so you can’t extend it!

 

Now in my case I just need the “refine your search” feature + I only want to search the people scope so I’ve made some adjustments to Steven Van de Craen's original wildcard search solution.

 

By looking at the sealed class from the “ PeopleCoreResultsWebpart “ I found and included the methodes required for the refine feature (CollectRefinementData – SortRefinementDataForColumn – SetSortedRefinementDataOnHiddenObject - GetXPathNavigator). And off course I fixed the scope to only search for people.

So now I have all the functionality I need by simply extending the “CoreResultsWebPart”.

 

You can find an example of the code here as the methods are just too much to post here. Of course you can always Reflector the “PeopleCoreResultsWebPart” if you need any of the other functionality’s, it probably won’t be easy as I haven’t come across someone who reverse engineered the entire webpart.

 

Hope this helps someone out, I’m sure glad I figured it out so I didn’t have to choose between wildcard search or my nice people search functionality's.

 

Gr Tom

Published: 12/3/2010  11:14 AM | 0  Comments | 0  Links to this post

Sep 222010

Get the preferred search center url from the MySite settings of your SSP

 

When creating some custom MySite code we wanted to link back to the searchcenter from my MySite but instead of using a webpart property we wanted to create our links the same way SharePoint does in the original MySite: with the “Preferred Search Center” location in the MySite Settings of your SSP. In the end it took me more time to find this property and a way to access it because it’s a non-public property so I thought it was worth a post seeing as I didn’t find anything else online for this.

 

//Get your current context (or the context of the SSP in question if that’s not the one your running in)

ServerContext current;

current = ServerContext.Current;

 

//Get the UserProfileApplication

object userProfileApplication = current.GetType().GetProperty("UserProfileApplication", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(current, null);

 

//Get the canonicalSearchCenterUrl

string preferredSearchCenterUrl = ((string)userProfileApplication.GetType().GetField("canonicalSearchCenterUrl", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(userProfileApplication));

 

Grtz,

Tom

Published: 9/22/2010  8:13 PM | 0  Comments | 0  Links to this post

 Next >>