Moved blogging engine

It’s been a little while since I last blogged. Well I’ve decided to change the blogging engine that I use from Graffiti to Subtext. Why? Well no real reason other than I’m not great at web design and there are more themes available for Subtext that I like. I reserve the right to move back though!

I did have some issues moving posts since Graffiti doesn’t have a BlogML export function, only import. Fortunately I was able to find a little utility on Curt’s blog at http://darkfalz.com/post/2009/04/14/Graffiti-To-BlogML-Exporter.aspx that allowed me to export by blog and comments although it did lose some of the names against the comments, sorry about that those that posted.

Installing CrashPlan on WHS part 2

In my previous post "Installing CrashPlan on WHS" I looked at installing CrashPlan on my home server and making it use UNC paths. In this post I was originally intending to look at what was needed to perform a backup between two home servers using a backup seeded from a portable hard disk.

I did manage to get all of that set up and working and was about to post when my friend noticed a problem. For some reason his backup files got erased and CrashPlan started a full backup over the net, this was going to take nearly 2 months.

After restoring the backup from portable hard disk again and starting things off it did the same thing again. So for now we've decided to uninstall CrashPlan until we have time to look into what's going on.

Installing CrashPlan on WHS

I've been looking at a backup solution for my home server for a bit. Now I'll forgive you at this point if you are thinking why do you need a backup solution for WHS when it does duplication.

Well several reasons but the main one being I want an offsite copy of most of the server contents in case of theft or fire. There are plenty of solutions out there for this but most of them require you to upload your files to the cloud and that is rather slow when trying to send a TB or so over a 800kbps uplink.

CrashPlan has the nice feature that you can back up to a friend's machine and you can seed the backup locally. So the plan is to get a new removable hard disk, backup, take to friends then update over the net.

Installing CrashPlan

I downloaded CrashPlan (www.crashplan.com) and installed it on my home server. I went to add my folders to the sources for backup and immediately hit a problem. CrashPlan doesn't let you specify a UNC path for the source (or the backup archive folder for that matter). Now I could just use D: but recommended practice for WHS is to always access data through the UNC paths so that's what I'd like to do.

The reason for this is that CrashPlan runs as SYSTEM and this account doesn't have network privileges and thus cannot access UNC paths.

To get around this I just changed the service to run as administrator and manually edited the %programfiles%/crashplan/conf/my.service.xml file to use UNC paths. The easiest way to do this is to add a dummy directory using the UI then find it in the config and change it. Use / instead of \ in the config file as it's a Java app and needs that.

I've only tested scanning to see if it can read the files and it seems to work, getting a removable drive and doing a backup is the next step.

Issues

Doing the above has 2 main issues, first you are running a service that provides a remote access interface on the internet as administrator, the second is that administrator may not have permissions to read the files being backed up.

To be honest both of these issues are present with CrashPlan anyway, it runs as SYSTEM and exposes the remote interface and SYSTEM can be denied permission on ACLs and so prevent backups from working. Fortunately WHS seems to create directories with ACLs that have both SYSTEM and Administrator in them with Full Control so it should work, I'll just have to remember not to change the ACLs on any files to remove those permissions.

Ideally the service interface should be running in a separate service with limited permissions and the backup engine service should be running as a user in the backup operators group.

I did initially try creating a new user in the backup operators group and run CrashPlan as that user, unfortunately CrashPlan doesn't use backup semantics when opening the files for backup and as such the ACL bypassing of the backup operators group doesn't kick in and it still can't access protected files.

I have suggested to the developers that the split the remote interface from the backup engine and use backup semantics when calling CreateFile() to access the files during backup. I'll let you know if I hear anything from them.

In the meantime I'm hoping the configuration I've built works ok, I'll follow this post up once I've got my external drive and have a backup done.

Calling WCF services with an invalid SSL certificate

A useful little snippet when using WCF with web services that have test SSL certificates.

When you call a service in WCF it's still using the underlying .NET classes in System.Net so it's actually here that you need to tell to ignore the invalid SSL certificate.

As it turns out this is very easy, all you need is the snippet below and it's good. Obviously you shouldn't deploy to a live environment with this code since it essentially says all certificates are valid but it's a handy trick to get a service working with any SSL certificate for testing.

ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true; };

Restart required when installing SQL Server 2008

I just tried installing SQL Server 2008 and kept getting an error during the setup support rules phase of the install. It was insistent that my machine needed a reboot, after rebooting a few times I was pretty sure it didn't really need a reboot.

After a little bit of trawling around I found this thread on the MSDN forums. Basically navigate to "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager" and delete any values in "PendingFileRenameOperations".

Thanks to the post from Tomas Leung for that, I can now install SQL Server 2008.

 

About

I'm Robert Garfoot and I'm a geek. There I've admitted it. This is my personal blog mainly covering computer related stuff but there may be a few other ramblings on here too.

I'm currently working as an Application Developement Consultant for Microsoft in the UK. If you'd like to have a look at our team we have a blog on MSDN. There are some very bright people on the team so it's worth a look.

Outside of work I enjoy a few recreational activities such as Archery (shooting at the Bowmen of Warfield club), reading and playing MMOs.

Transferring large files using WCF

Recently I wanted to send large files (several GB) from a rich desktop client to a web service. The client and service communicate using WCF and I thought that this would be quite easy. As it turns out it is but there are a few gotchas on the way.

Streaming

The first gotcha is that you do not want to buffer the message as you send it. Depending on the amount of RAM and the size of the file this may or may not be a problem on the client but it's almost certainly going to be a problem on the server with multiple clients sending files at the same time.

To solve this you can either write a service contract that accepts the file in chunks or use WCF streaming. In this instance I decided to use streaming.

Streaming in WCF does have some drawbacks which I'm not going to go into here so it's not suitable for everything but it was fine in this situation.

To use streaming you simply pass parameters of type 'Stream' and change the config to use streaming. This is a per endpoint setting so I set up a separate endpoint for the upload service.

Passing Metadata

The next problem I found was how to pass metadata with streams. Since I'm uploading via HTTP I want to make sure the file gets there intact so I'd like to transfer a checksum with the file (along with other details). WCF will not let you have any other parameters if using streams so how do you pass it.

Since using sessions with streaming can result in unpredictable behaviour there are a couple of options open. The first is to return a GUID (or other unique ID) after uploading the file and then allow a separate operation to set the metadata for that GUID and then link it to the previous file upload.The other option, and the one I chose, is to explicitly specify the message and send the metadata in the message header.

Max Message Sizes

The next issue I faced was the size of the messages, you need to ensure that the maxReceivedMessageSize is set large enough for your largest file. Since headers are always buffered, even when streaming, you want to ensure that this doesn't result in DOS attacks by settings maxBufferSize to something reasonable such as 64K. This will allow large streamed bodies but limits the size of the headers.

Gotchas

So that's it, all set up and working now. Well not quite. As I mentioned at the start there are a few gotchas with this.

First, the VS webdev server (Cassini) cannot handle streaming over HTTP. This is simple to fix, use IIS or self host in a console app or windows service.

Second, IIS uses the ASP.NET maxRequestLength setting for the max length not the WCF setting. You need to add this to your web config.

Third, IIS cannot transfer more than 2GB of data. You'll need to self host to get around this if you need to send more data than that.

Fourth, timeouts can occur so you need to increase the send/receive timeouts in WCF.

Code

So here are samples of the code bits I used.

web.config - server

<system.web>
    <httpRuntime maxRequestLength="2097151" />
</system.web>

<basicHttpBinding>
    <binding name="FileSenderService.StreamedBinding"
                 transferMode="StreamedRequest" maxBufferSize="65536"
                 maxReceivedMessageSize="2000000000" messageEncoding="Mtom"
                 receiveTimeout="00:10:00">
    </binding>
</basicHttpBinding>

 

app.config - client

<basicHttpBinding>
    <binding name="BasicHttpBinding_IFileTransfer" sendTimeout="00:10:00"
             messageEncoding="Mtom"transferMode="StreamedRequest" />
</basicHttpBinding> 

Contracts

[MessageContract]
public class SendFileRequestMessage
{
    [MessageHeader(MustUnderstand = true)]
    public FileTransferInfo FileInfo;

    [MessageBodyMember(Order = 1)]
    public Stream FileData;
}

[ServiceContract]
public interface IFileTransfer
{
    [OperationContract]
    void SendFile(SendFileRequestMessage request);
}

[DataContract]
public class FileTransferInfo
{
    [DataMember(Order = 1, IsRequired = true)]
    public string Name { get; set; }

    [DataMember(Order = 2, IsRequired = true)]
    public byte[] Checksum { get; set; }
}

The following blogs / articles were useful in sorting this out.

 

Web test recorder problems in IE

Visual Studio Team System has some nice testing feature, amongst which is the ability to record and playback web browsing as part of a web test. The recorder makes building web tests much easier that writing the test scripts by hand. I went to record a new web test today but the test recorder didn't appear.

I've recently installed IE8, I don't know if this was the culprit for breaking the recorder or not but fortunately the fix was quite easy. After a bit of searching I came across an entry on Michael Taute's blog at blogs.msdn.com/mtaute/archive/2007/11/09/diagnosing-and-fixing-web-test-recorder-bar-issues.aspx.

This article contains several possible fixes for these kinds of problems, the one that worked for me was regarding VSTS 2008 and Vista 64 (I'm running on Server 2008 64 bit). I've included that particular fix below but have a look at the original article for others.

VSTS 2008 : Vista (64 bit) : Recorder bar does not appear when recording a new webtest

Fix:  Vista caches the list of explorer bars you have available and the recorder bar was not included in your list.  The fix is to force Windows to rebuild that cache.  To do this, first make sure you have all Internet Explorer instances shut down, then open the 32 bit registry editor and delete the following keys:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000046}

[Note: by default, the 32 bit registry editor is located in %WINDIR%\SysWow64\RegEdt32.exe]

The next time you boot Internet Explorer, your explorer bar cache will be rebuilt and the recorder bar should be available.
 

 

Installing SwissCenter on WHS

I use a Pinnacle ShowCenter for as my network media player for playing back music and movies on my A/V equipment. It's a nice bit of hardware but the software it comes with doesn't fit my needs. Fortunately the player uses a simple web browser for it's UI and this is served from the Pinnacle server so it's possible to replace the server component with a new one that provides whatever functionality you like.

There are a few open source server packages out there for the ShowCenter (and other Syabas based media devices) but the one I use, and in my opinion the best of them, is the SwissCenter (available from www.swisscenter.co.uk).

This software is written using PHP, Apache and MySQL and runs on either Linux or Windows. However, on Windows there is a nice simple install option using another project called Simese (Simple Media Server). This provides a single installer for the Simese media server, PHP, MySQL and SwissCenter.

You can install this on a WHS quite easily, I just downloaded the latest build (1.45 Simese and 1.20.1 SwissCenter at the time of writing), logged on via terminal services and installed it. I made sure that I entered the media locations as UNC paths and that the user Simese was running as had access to the media locations and it all works fine. Upgrading the box to 2GB helped though since running this stuff on a standard HP MediaSmart with 512MB is a little slow.

In addition to installing Simese and SwissCenter I also installed MusicIP. This is an optional component that SwissCenter can use in order to create custom playlists based on similar music, you simply select a track in SwissCenter and then get a link to 'play similar', this functionality uses MusicIP to generate the playlist which the SwissCenter then plays.

Installing MusicIP on the WHS was also pretty easy, I just followed the instructions for a standard install on Windows. The only thing I needed to change was to change the user the service runs as to ensure it had access to my media.

Overall a nice little setup and I'm quite happy I can run it all from my home server now.

Using SSL certs from IIS on WHS with Apache

I recently installed a Subversion server on my WHS box. In the past I've usually installed and configured Apache and mod_svn myself, but this time I decided to use the pre-packaged version from the people behind VisualSVN.

This version still uses Apache as the server however. Now I don't like sending passwords in the clear over the net, especially to things like a source repository. The default install of VisualSVN does support SSL and comes with an SSL cert that you can use. However, since I have a cert for my WHS box anyway I thought it would be nice to be able to reuse that. In the end it was quite easy, the steps are below.

  • Download OpenSSL from http://www.slproweb.com/products/Win32OpenSSL.html. You can download the Light version for this.
  • Install on the machine you are going to work on (I did this on my desktop, doesn’t have to be WHS).
  • Ensure that the OpenSSL bin directory is in your path (makes things easier)
  • Export the cert from IIS or certmgr.msc on the WHS
  • In IIS go to site properties for the WHS site and then directory security and click the server certificate button
    • Then select export a current certificate and give it a filename
  • Make sure you export the private key along with the cert (IIS export does this automatically) but using certmgr.msc you'll need to select it
  • Use OpenSSL to extract the private key and cert
  • First export the key into a passworded file, then export the cert, finally remove the password from the key so Apache / VisualSVN can use it
    • openssl pkcs12 –in mycert.pfx –nocerts –out key.pem
    • openssl pkcs12 –in mycert.pfx –clcerts –nokeys –out cert.pem
    • openssl rsa –in key.pem –out server.key
  • Finally you have a cert (cert.pem) and key (server.key) you can use with Apache and VisualSVN. Just update the httpd.conf files to use those files. I dropped them into c:\certs on my box so I can share them between multiple apps.