Wednesday, 23 April 2008

Windows XP continues to run once HDD removed

What happens when you remove the boot volume and re-insert? - Nothing :) - Windows continues to run right through until the HDD is put back in.

My colleague Dave Cromar was asking me how to remove the hard disk from his laptop (HDD due to be replaced today) so I went round to show him. He had already removed the screws, so I just slid it out of the chassis of the laptop - it was that point where I realised his machine was still switched on =D

We put it back in, and to our great surprise Windows XP continued to function - so we did it again but this time with the camcorder!

He has continued to use it all day without a reboot, and no problems. Check the link for the video on youtube.



read more | digg story

Monday, 21 April 2008

Cutting your Losses

Just read Peter Bright's article on a Windows user converting to Mac, but from a very well balanced and unique developer perspective.

I have to say that placing myself in mainly the .NET Framework, my experience of Windows behind the scenes isn't as tarnished with bad experience, but from my general usage of Windows I can really see where Peter is coming from.

It seems like Microsoft's unwillingness to make major breaking changes in their API (and therefore break many high value enterprise apps) is a major contributor to the general poor quality of Windows today. Apple on the other hand cut their losses, deprecating functionality and introduced a new OS from NeXT enabling them to write modern powerful APIs such as Cocoa. This allowed them a platform to support several high quality industry standard apps such as Final Cut Pro, Aperture etc.

From the article:
"Microsoft has never done anything so bold as Apple's OS X transition. It developed a new, modern OS, but did so in the early 1990s: Windows NT. And although Windows NT ticked the right boxes at the time—protected memory, preemptive multitasking, multiprocessor, written in platform-independent C—in places it was never even close to modern. Its APIs were based on the Win16 API from 16-bit Windows. This was a deliberate decision, as it made it easier to migrate 16-bit apps to the new 32-bit platform, and at the time it probably made sense. But it means that nowadays the 64-bit API (Win64) still reflects decisions made 20 years ago."

I can understand the predicament - but in software my humble opinion is that the quicker you cut your losses the better - code the right way from the beginning and re-factor as much as possible.

Perhaps my opinion is blinkered, blindly ignorant, who knows - you can always post a comment :)

Wednesday, 2 April 2008

WCF: Hosting multiple WCF services as one single service

On Monday I needed to split up a WCF service I had written for SharePoint into multiple services, one for Document Libraries, one for Lists, and another 'Common' service which has some standard methods like Ping() and GetVersion().

It didn't make sense to me to have all this functionality for lists, document libraries and common stuff all in one service, yet I didn't want to have to host 3 separate services on different WCF endpoints and port numbers.

I couldn't find anything about this on the web or in the excellent WCF book "Learning WCF" by Michele Leroux Bustamante. Luckily me and my colleague Dave Cromar worked out how to achieve this!

We have our 3 seperate Interface contracts:

[ServiceContract(Name = "Utility", Namespace = Constants.COMMON_SERVICE_NAMESPACE)]
public interface IService

[ServiceContract(Name="Documents", Namespace = Constants.DOCUMENTS_SERVICE_NAMESPACE)]
public interface IDocumentService

[ServiceContract(Name = "Lists", Namespace = Constants.LISTS_SERVICE_NAMESPACE)]
public interface IListService


...each one has the various methods defined in the interface and decorated with the WCF attributes such as OperationContract and FaultContract, as per normal.

Now, in our concrete implementations of these interfaces, instead of having 3 seperate classes, we have one class, but defined as a partial class, split up into 3 seperate CS files, each class definition implementing it's corresponding interface, IService, IDocumentService and IListService.

So it looks like this:

Service.cs:

[ServiceBehavior(Name="SharePoint")]
public partial class Service : IService
{
#region IService Members

// Common Service, ping, getVersion etc.

// Implementation of Service class goes here
...
#endregion
}


DocumentService.cs:

public partial class Service : IDocumentService
{
#region IDocumentService Members

// Implementation of DocumentService interface goes here
...

#endregion
}


ListService.cs:

public partial class Service : IListService
{
#region IListService Members

// Implementation of ListService interface goes here
...

#endregion
}


This all compiles nicely - note that the 3 class definitions have to be in the same namespace because they are all the same class (partial).

One last thing - the WCF app.config configuration:

Basically, the configuration is exactly as per a normal configuration with a single service node defined, but with three separate endpoints:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="MyNamespace.Service"
behaviorConfiguration="MyNamespace.ServiceBehavior">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="Common"
binding="netTcpBinding"
bindingConfiguration="netTcpStreaming"
contract="MyNamespace.Common.Contract.IService" />
<endpoint address="Documents"
binding="netTcpBinding"
bindingConfiguration="netTcpStreaming"
contract="MyNamespace.Documents.Contract.IDocumentService" />
<endpoint address="Lists"
binding="netTcpBinding"
bindingConfiguration="netTcpStreaming"
contract="MyNamespace.Lists.Contract.IListService" />
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000" />
<add baseAddress="net.tcp://localhost:9000" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyNamespace.ServiceBehavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<!-- Max file size 4GB, max message size 64KB, timeout 1 hour -->
<binding name="netTcpStreaming" transferMode="Streamed" maxReceivedMessageSize="4294967296" maxBufferSize="65536" sendTimeout="01:00:00" />
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>


Notice the three endpoints defined with the different address values - these get appended onto the base address defined, so that when a client discovers the service, the app.config created will have three seperate bindings (one for each service interface), and three seperate endpoints. Each endpoint will have different addresses, but crucially, the same base address:


<endpoint address="net.tcp://localhost:9000/Common" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_Utility" contract="Service.Utility"
name="NetTcpBinding_Utility">
<identity>
<servicePrincipalName value="host/localhost.domain" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:9000/Documents"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Documents"
contract="Service.Documents" name="NetTcpBinding_Documents">
<identity>
<servicePrincipalName value="host/localhost.domain" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:9000/Lists" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_Lists" contract="Service.Lists"
name="NetTcpBinding_Lists">
<identity>
<servicePrincipalName value="host/localhost.domain" />
</identity>
</endpoint>


This allows us to split out our service into seperate logical entities, but still expose it in one single place - job done!

Any questions - please use the comments.