Skip to content
Mar 24 / Michaël Hompus

Microsoft extends support for WSS 3.0, SharePoint 2007 and Project Server SP1

As I wrote in January "WSS 3.0, SharePoint 2007 and Project Server SP1 support ends soon". But today I discovered Microsoft has extended the support for installations of Windows SharePoint Services 3.0 SP1, Microsoft Office SharePoint Server 2007 SP1 and Project Server 2007 SP1.

On the Microsoft Lifecycle pages for "Windows SharePoint Services 3.0 Service Pack 1" and "2007 Microsoft Office Servers Service Pack 1" the new retirement date is set for July 13th, 2010.

Mar 22 / Michaël Hompus

Localizing the Microsoft Surface Shell

The Microsoft Surface is a Windows Vista computer running the Microsoft Surface Shell. This shell is by default localized for US English. It’s possible to localize for other locales, but there is no configuration screen to set the desired localization.

This post will summarize the different steps to localize the Surface shell.

Microsoft Surface Device vs. Microsoft Surface Simulator

The settings work for both the Microsoft Surface device and the Surface Simulator.

Note for x64 machines (Running the SDK)

If you’re running the Surface Simulator on a x64 machine (see my post about "Installing the Microsoft Surface SDK on Windows 7 x64") the registry entries are slightly different.

For x86:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0

For x64:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Surface\v1.0

All my examples in this post will use the x86 path.

Setting the Surface Shell interface language

With service pack 1 the Shell now supports 10 UI languages.

Language UILanguageName value
Danish da-DK
Dutch nl-NL
English (United States) en-US
French fr-FR
German de-DE
Italian it-IT
Korean ko-KR
Norwegian (Bokmål) nb-NO
Spanish es-ES
Swedish sv-SE

 

To set the required language you need to edit the registry.

Look for the following key

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0\InternationalSupport

Change the UILanguageName value into the desired language name you find in the table. For example to set the language to Dutch you enter "nl-NL".

Restart the shell

Screenshot displaying the modified registry entry to localize the language of the Shell.

The modified registry entry to localize the Surface Shell language.

Surface button displaying "Close everything" (English) as caption.

Close button with caption "Close everything" in English (default).

Surface button displaying "Alles sluiten" (Dutch) as caption.

Close button with caption "Alles sluiten" in Dutch (localized).

Setting the Surface Keyboard mapping

There are 19 supported keyboard mappings.

Keyboard layout InputLanguageID value
Belgian (Comma) 0x1080c
Belgian French 0x80c
Canadian French 0×1009
Canadian Multilingual Standard 0×11009
Danish 0×406
French 0x40c
German 0×407
Italian 0×410
Korean 0×412
Latin American 0x80a
Norwegian 0×414
Spanish 0x40a
Swedish 0x41d
Swiss French 0x100c
Swiss German 0×807
United Kingdom 0×809
United Kingdom Extended 0×452
US English 0×409
US-International 0×20409

 

To set the desired keyboard mapping you need to edit the registry.

Look for the following key

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0\InternationalSupport

Change the InputLanguageID value into the desired keyboard mapping you find in the table. For example to set the shell to Korean you enter "0×412" (Hexadecimal).

Restart the shell

Screenshot displaying the modified registry entry to localize the mapping of the Surface Keyboard.

The modified registry entry to localize the Surface Keyboard mapping.

Keyboard using US English mapping.

Surface Keyboard with US English mapping (default).

Keyboard using Korean mapping.

Surface Keyboard with Korean mapping (localized).

Setting the Surface Date and Number formatting

For date and number formatting you can use all locales supported by the .NET Framework. The complete list can be found on the Language Identifier Constants and Strings MSDN page.

Just combine the primary language, for example: Dutch (nl), with the sublanguage, for example Netherlands (NL): nl-NL.

To set the desired date and number formatting you need to edit the registry.

Look for the following key

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0\InternationalSupport

Change the LocaleName value into the desired formatting locale. For example to set the formatting to Dutch you enter "nl-NL".

Restart the shell

Screenshot displaying the modified registry entry to localize the formatting of date and time values.

The modified registry entry to localize the date and number formatting.

Date and time formatted in US English: "Monday, March 22, 2010 12:00:00 AM".

Date formatting in US English (default).

Date and time formatted in Dutch: "maandag 22 maart 2010 0:00:00".

Date formatting in Dutch (localized).

Mar 3 / Michaël Hompus

Installing the Microsoft Surface SDK on Windows 7 x64

If you want to develop for the Microsoft Surface you need a Surface device. But using the device to develop is not always practical, specially when there are more developers than Surface devices. The solution for this is to install the Surface SDK Workstation Edition on your local development machine. This post will address some limitations you have to work around.

The Microsoft Surface SDK

The Microsoft Surface SDK was released to attendees of the PDC in 2008, where I was one of the lucky few. You can still view the "Developing for Microsoft Surface" session on Channel 9.

With the PDC 2009 the Microsoft Surface SDK 1.0 SP1 Workstation Edition was publically released.

Prerequisites

Before you can install the Surface SDK there are some prerequisites:

When you’re running Vista x86

Assuming you’re not running Windows Vista Starter Edition you can install the Surface SDK without problems and can start developing immediatly!

When you’re not running Vista or x86

Error dialog diplaying the message: "Your system does not have the correct version of Windows Vista. You must install Microsoft Surface SDK 1.0 SP1, Workstation Edition on a 32-bit version of Windows Vista with Service Pack 1 (SP1). Microsoft Surface SDK 1.0 SP1, Workstation Edition also does not support Windows Vista Starter edition."

Well let’s face it, Windows Vista is old and gone, and everybody is running Windows 7 nowadays. So does this mean no more Surface development?

Lucky enough Brian Peek wrote a great blog post about this and I will summarize it here.

Naturally this makes the installation not supported by Microsoft.

Extracting the installer

There are two installers on the web available at the moment. An executable if you download the SDK from the partner site and a MSI if you download the SDK from the public Microsoft download site.

For the MSI:

msiexec /a SurfaceSDKWE.msi /qb TARGETDIR=c:\surface

For the executable:

"Microsoft Surface SDK 1.0 SP1, Workstation Edition.exe" /extract c:\surface

Patching the installer

Get the Orca tool from the Windows SDK, or if you don’t want to download 4GB for a tool not bigger than 2MB, try a less supported site. ;)

Open the extracted SurfaceSDKWE.msi file with Orca.

Select the table "LaunchCondition"

Select the row with "Installed OR NOT VersionNT64" and choose "Drop row"

Save & Close Orca

Patching the Custom Actions

This is only needed on a x64 machine.

Get the CorFlags tool from the Windows SDK, or if you still don’t want to download 4GB, try an even lesser supported site. :)

Open a command prompt with elevated privileges (Run as administrator).

Go to the location of the extracted installer

cd "Microsoft Surface\v1.0"

CorFlags setupcustomaction.exe /32BIT+ /Force /nologo

Ignore the warning with the code CF011 about strong named signing.

Command prompt showing the warning "corflags : warning CF011 : The specified file is strong name signed.  Using /Force will invalidate the signature of this image and will require the assembly to be resigned." after execution.

Installing the SDK

This is pretty straightforward.

First screen of the Microsoft Surface SDK 1.0 SP1, Workstation Edition Setup

If you are running on a x86 system you can start developing!

Patching the executables

This is only needed on a x64 machine.

To make sure the Surface SDK executables are using the x86 CLR you have to patch them all.

cd "C:\Program Files (x86)\Microsoft SDKs\Surface\v1.0\Tools\GenTag"

for %i in (*.exe) do CorFlags %i /32BIT+ /Force /nologo /UpgradeCLRHeader

cd "C:\Program Files (x86)\Microsoft SDKs\Surface\v1.0\Tools\Simulator"

for %i in (*.exe) do CorFlags %i /32BIT+ /Force /nologo /UpgradeCLRHeader

cd "C:\Program Files (x86)\Microsoft SDKs\Surface\v1.0\Tools\SurfaceStress"

for %i in (*.exe) do CorFlags %i /32BIT+ /Force /nologo

cd "C:\Program Files (x86)\Microsoft Surface\v1.0"

for %i in (*.exe) do CorFlags %i /32BIT+ /Force /nologo

Patching the Sample Applications

This is only needed on a x64 machine.

Modify all projects files (*.csproj) and change the build type from "Any CPU" to x86.

For example, add the following to the appropriate PropertyGroup tags:

<PlatformTarget>x86</PlatformTarget>
Feb 2 / Michaël Hompus

Prevent user to recall or delete a timesheet after approving

Working on a Project Server project we discovered it’s quite easy to get issues with data integrity when users start retracting and deleting timesheets. After discussing the issue with Microsoft they gave us a workaround which solves our problem.

The problem

After a user has submitted a timesheet and the timesheet manager approves this timesheet as well the data is exported to an external system for invoicing.

The user however still is able to retract the timesheet, modify it and resubmit. It’s even possible to delete the timesheet.

Our first thought was to close the period of the submitted timesheets. But this only works partially. The user can’t modify the timesheet anymore, but is still able to retract and delete it. Not a very solid solution.

The cause

After discussing the issue with Microsoft we got this reaction:

Period close is designed to block new entries not changes which include deletions.

So this is pretty much "by design".

The solution

Lucky enough for us the answer of Microsoft didn’t stop there:

There is a Flag field in the PSI dataset that is called TS_IS_PROCESSED.

This can be set by a custom event or script when the period is closed for timesheets within the period or as originally designed, when the timesheet has been exported to a third party system for processing.

In 2007, we are looking at the data from a position where the system of record can modify the data and to help customers determine when Project Server is no longer the system of record, we are leaving it up to the customer to check that flag.

After the flag is set to true then no action can be performed on the timesheet except by duly authorized system administrators for adjustments theoretically coming from the third party system.

I already knew about the TS_IS_PROCESSED property as it is described by the Project Server SDK. But the description there only states:

Indicates whether the timesheet is finalized and should not be changed.

When TS_IS_PROCESSED is true, the timesheet cannot be recalled, changed, or deleted.

The, important, missing peace of information is that this field is supposed to be altered by custom code instead of project server itself.

Jan 27 / Michaël Hompus

Calling a SharePoint Web Service from Silverlight over HTTP and HTTPS

The past couple of weeks I’m working with Silverlight controls embedded in SharePoint 2007.

For one of the controls I need to retrieve the data using the Search Query Web Service.

I was using the following code:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var endpoint = new EndpointAddress(GetParam("SharePointWeb") +
                                                       "/_vti_bin/search.asmx");
    var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
                      {
                          Name = "QueryServiceSoap",
                          MaxReceivedMessageSize = 2147483647,
                          MaxBufferSize = 2147483647
                      };

    var client = new QueryServiceSoapClient(binding, endpoint);
    client.QueryExCompleted += this.ClientQueryExCompleted;
    client.QueryExAsync(GetParam("Query"));
}

This was working perfectly in the development environment. But when deploying the control to the production environment it didn’t work.

After some digging I found that the control did work, but only when the page was visited over an HTTP connection. As everybody accesses the page over an HTTPS connection I was pointed in the direction of the connection between the control and the web service.

As can be seen in the code the WCF client is used and I remembered that the binding security mode is different if you want to work with HTTPS. So I changed the BasicHttpSecurityMode from None to Transport.


-var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)

+var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)

After deploying the control again it worked nicely over the HTTPS connection, so I know what the source of my problem is. But naturally I want a generic solution so the configuration of the access mapping is not influencing the functioning of the control.

The question is how to detect if the control is hosted on a page over an HTTP or HTTPS connection. This can be found in the SilverlightHost.Source property which can be compared against the Uri.UriSchemeHttp field or the Uri.UriSchemeHttps Field.

As a result this is my final code:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var basicHttpSecurityMode =
        (Application.Current.Host.Source.Scheme == Uri.UriSchemeHttp)
            ? BasicHttpSecurityMode.None
            : BasicHttpSecurityMode.Transport;

    var endPoint = new EndpointAddress(GetParam("SharePointWeb") +
                                                       "/_vti_bin/search.asmx");
    var binding = new BasicHttpBinding(basicHttpSecurityMode)
                      {
                          Name = "QueryServiceSoap",
                          MaxReceivedMessageSize = 2147483647,
                          MaxBufferSize = 2147483647
                      };

    var client = new QueryServiceSoapClient(binding, endPoint);
    client.QueryExCompleted += this.ClientQueryExCompleted;
    client.QueryExAsync(GetParam("Query"));
}

Works like a charm.

Jan 15 / Michaël Hompus

MySitePublicWebPartPage throws NullReferenceException with August Cumulative Update

The problem

With the introduction of the August Cumulative Update for SharePoint 2007 (KB973399) we encountered "System.NullReferenceException: Object reference not set to an instance of an object." on all pages inheriting from MySitePublicWebPartPage.

Stack Trace of the exception

As can be seen in the stack trace the error occurs from a call by the ProfilePropertyImage control which is on the page by default.

The cause

This call was not present in the control prior to the august update, so let’s take a look at the description of the update (KB973409).

A Shared Services Provider administrator edits the About me property or the Picture property to make the property display "Only me." However, these properties continue to be visible when the profile owner sets their As Seen By option to "Everyone," "My Colleagues," "My Workgroup" or "My Manager" on their own Person.aspx page.

So this explains why the control was changed, it now looks if the image should be rendered for the current visitor of the page.

The reason

We already know the problem starts inside the ProfilePropertyImage which is calling the MySitePublicWebPartPage.GetEffectivePrivacy method. This method reads the value of the MySitePublicWebPartPage.PrivacySelected property. Inside the getter of the property the following code is used:

object obj2 = this.ViewState["__PrivacySelected__"];
return (Privacy) obj2;

As we all know SharePoint’s code is never about defensive programming and so is the case here if there is no viewstate property available, it will return a null. And of course there is no check anywhere for that.

But this code works for the default person.aspx page, so the setter for this property has to be called somewhere. Analysis of the code shows only the AsSeenBy class ever calls the setter. As this control is on the person.aspx page by default the property is set and that page works fine. As we don’t have this control on our page we get a NullReferenceException.

The solution

If you’re bound to the August release the solution is simple: add the AsSeenBy control to your page. :)

But what if you don’t want to have the control on your page? We get lucky, because if you don’t make it visible it will still work, so add:

<SPSWC:AsSeenBy runat="server" id="ddlAsSeenBy" SelectionMode="Single"
                autopostback="True" Visible="False" />

If you’re not bound to the August upgrade you can upgrade to the October Cumulative Update or newer. Microsoft has fixed the issue in those versions.

Jan 11 / Michaël Hompus

WSS 3.0, SharePoint 2007 and Project Server SP1 support ends soon

Update March 24th, 2010: Microsoft extends support for WSS 3.0, SharePoint 2007 and Project Server SP1

 

Stefan Goßner reminds us of the fact that support for WSS 3.0 SP1, SharePoint 2007 SP1 and Project Server SP1 will soon end.

Support ends when the next service pack is out for over a year. And SP2 was released April 28th 2009 so SP1 won’t be supported from April 29th 2010, so roughly in 3 months.

Be sure to test & deploy your upgrade soon!

Jan 8 / Michaël Hompus

Correcting time drift with CentOS on Hyper-V

I was having trouble with the clock in my Linux Hyper-V VM’s.The time was constantly drifting forward. Using NTP only slowed the drift a bit down but often NTP gave up after several days.

I tried a lot of NTP configurations, but basically the local clock was just unreliable. Even using rdate every 10 minutes was already showing backwards jumps of several seconds. As one of my VM’s is running dovecot this really was a problem because dovecot hates time moving backwards.

I finally found the solution posted by Mat Mirabito in his blogpost “Linux (specifically CentOS running trixbox) gains excessive time on system clock”.

Edit your grub.conf and add the following to the kernel line:

divider=10 clocksource=acpi_pm

After this it works like… clockwork :)

Jan 7 / Michaël Hompus

Running CentOS 5.x on Hyper-V

I’m running Linux in Hyper-V VM’s since the launch of the Windows Server 2008 RTM. But in the beginning it was quite complex to get real performance and support for the network drivers.

But recently with the launch of R2 there are also new Linux Integration Components which also work for Windows Server 2008 RTM. So here is the list of steps to install CentOS with the integration components.

Download the latest CentOS distribution from http://mirror.centos.org/centos/5/isos/ (I use the x86_64 version).

Create a VM

I suggest >400MB memory

Add a Legacy Network Adapter (connect to network)

Add a Network Adapter (connect to network)

Mount the CDROM and install CentOS (I used a minimal setup)

After the installation is done make certain you’re up to date

yum update

Install the required components for the Linux Integration Components

yum install gcc make gnupg kernel-devel

Reboot into the latest kernel

Download the Linux Integration Components

Mount the CDROM

mkdir -p /mnt/cdrom

mount /dev/cdrom /mnt/cdrom

cp -rp /mnt/cdrom /opt/linux_ic

umount /mnt/cdrom

Build the drivers

cd /opt/linux_ic

./setup.pl drivers

If you get the message “No kernel-xen-devel or kernel-source package installed. You must install this package before installing the drivers.

Edit the setup.pl file and change the following

-$kernel = `rpm -q kernel-xen-devel`;

+$kernel = `rpm -q kernel-devel`;

If everything went OK you can now see a new nic called seth0 using ifconfig

You can now remove the Legacy Network Adapter.

Remember, every time you update the kernel you have to run the setup.pl drivers command.