Skip to content
/

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.

The Microsoft Surface (the table, not the tablet) 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 ) 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.

LanguageUILanguageName value
Danishda-DK
Dutchnl-NL
English (United States)en-US
Frenchfr-FR
Germande-DE
Italianit-IT
Koreanko-KR
Norwegian (Bokmål)nb-NO
Spanishes-ES
Swedishsv-SE

 

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

  1. Look for the following key
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0\InternationalSupport
  2. 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.
  3. 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 layoutInputLanguageID value
Belgian (Comma)0x1080c
Belgian French0x80c
Canadian French0x1009
Canadian Multilingual Standard0x11009
Danish0x406
French0x40c
German0x407
Italian0x410
Korean0x412
Latin American0x80a
Norwegian0x414
Spanish0x40a
Swedish0x41d
Swiss French0x100c
Swiss German0x807
United Kingdom0x809
United Kingdom Extended0x452
US English0x409
US-International0x20409

 

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

  1. Look for the following key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0\InternationalSupport
  2. Change the InputLanguageID value into the desired keyboard mapping you find in the table. For example to set the shell to Korean you enter 0x412 (Hexadecimal).
  3. 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 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.

  1. Look for the following key
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Surface\v1.0\InternationalSupport
  2. Change the LocaleName value into the desired formatting locale. For example to set the formatting to Dutch you enter nl-NL.
  3. 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).
Filed under Surface
Last update:
/

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 on you local development machine. This post will address some limitations you have to work around.

If you want to develop for the Microsoft Surface (the table, not the tablet) 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 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. 😉

  1. Open the extracted SurfaceSDKWE.msi file with Orca.
  2. Select the table LaunchCondition
  3. Select the row with Installed OR NOT VersionNT64 and choose Drop row
  4. 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. 🙂

  1. Open a command prompt with elevated privileges (Run as administrator).
  2. 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>
Filed under Surface
Last update:
/

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.

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.

/

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.
This was working perfectly in the development environment. But when deploying the control to the production environment it didn't work.

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.