NTFS Junction Points

Link. July 7, 2008. Comments [0]. Posted in: Tools | Vista

I spent some time this weekend organizing a few files and source code repositories. As part of this process, I wanted to take advantage of NTFS hard-links and junction points, both of which are supported on Windows Server 2003/8 and Vista.

I had no problems with hard-links at all. I'm using the ln.exe tool from http://www.flexhex.com/docs/articles/hard-links.phtml to create them, and it worked great right from the start (I could also use the "fsutil hardlink create" command).

Junction points, however, gave me quite a bit more trouble. I've used Junction points in the past very successfully. I work with some code bases that for many reasons expect to have certain directories in the C:\ drive, but I keep all my code in the E:\ drive.

For this I've used cross-drive junction points to have the folder in C:\ point to the real folder in E:\ and it's worked great for a couple of years. One other tool I've used for this sometimes is Junction Link Magic.

Yesterday, however, I discovered that on Windows Server 2003, if the junction folder was on the same drive as the target folder, it just wouldn't work correctly. I could create the junction just fine, and I could even see the contents of the directory through the junction using explorer, cmd.exe or PowerShell.

Actually trying to access any of the children through the junction would result in the error:

The filename, directory name, or volume label syntax is incorrect.

I tried both of the tools I mentioned before, and it just wouldn't work. I tried creating the junctions from WinServer2K8 (where they worked perfectly) and then using the drive from 2003, and it still wouldn't work. This was easy to test, by the way, since this is a VHD image I share between several virtual machines.

Eventually, fellow MVP Juan T. Libre insisted I tried the linkd.exe tool in the Windows Server 2003 Resource Kit. I was reluctant to it since the other tools could create working cross-drive junctions and I was starting to suspect an OS limitation, but I gave it a go.

Much to my surprised, linkd.exe was able to create working same-drive junction points on Windows Server 2003. My guess is that there's some (probably undocumented) detail about how the APIs need to be called that can affect whether this works correctly or not.

Looking at the junctions using the "fsutil reparsepoint query" command clearly shows that the Reparse Data is slightly different between cross and same drive junctions, but not sure what it means from the API point of view. Just something to watch out for.

The lesson: Use linkd.exe on Windows Server 2003 to create same-drive junctions.

Net.MSMQ and Poison Messages

Link. May 27, 2008. Comments [0]. Posted in: Vista | WCF

The Net.MSMQ Binding in Windows Communication Foundation has some built-in support for detecting and handling "Poison Messages".

One of the most useful ways of handling Poison Messages in queuing systems is to get them out of the way so that following messages can still be processed (if you're not doing in-order processing), but still keep the messages around so that they are not lost.

Unfortunately, this behavior is only supported by WCF in MSMQ 4.0 with the use of a poison sub-queue, which is new in the Vista and WinServer2k8 versions of MSMQ. It's really a shame because, honestly, this could've been implemented on MSMQ 3.0 just by using a separate queue instead of sub-queues.

Instead, we're stuck with the PoisonErrorHandler sample included in the SDK. The sample provides a way to mimic this behavior by introducing an IErrorHandler implementation that detects the poison message and moves it to another queue. To be able to do this, you need to set the binding properties so that the ServiceHost listening to the queue faults when the poison message is detected. The error handler then moves the message to a new queue and starts a new service host instance to resume processing of following messages.

The Sample itself isn't all that bad, but does provide insight into a rather significant feature left out of the way the Net.MSMQ Binding reports poison messages: All it provides the error handler with is the MSMQ LookupId of the poison message. Unfortunately, this LookupId is queue-specific and the exception does not provide information on which queue or at least which endpoint was the one that received the poison message, which is a huge gaping hole in this feature.

Because of that the LookupId is useless without more information provided out-of-band [1]. The sample works around this limitation by adding an entry in the <appSettings/> section of the app.config file with the path to the queue where messages are being received and the path to the queue to move poison messages to.

This works OK, until you need a single service host listening on multiple endpoints, and then the sample won't really work anymore because you don't know which of the endpoints caused the error.

Working around the limitation

I spent some time recently playing around with WCF and ran into this same problem, so I tried to find a way of working around this limitation and still use the basic functionality the sample provided.

I found one possible workaround, which seems to work so far in my limited tests. I'm not sure yet how well it will hold, as it seems to me there's always the possibility of some race conditions here, but let me illustrate at least the basic mechanics.

First we keep the basic code of the PoisonErrorHandler class. However, instead of using appSettings to keep track of the queue we're listening to, we just try to find out dynamically which endpoint configured for the service is causing the error, and extract the path to the queue from there based on the URI of the endpoint address.

To do this, in my implementation of IErrorHandler.HandleError() I grab the current OperationContext, reach out to the ServiceHost associated with it, and then iterate over the ChannelDispatchers attached to it. The one that's in the Faulted state is very likely the one that caused the MsmqPoisonMessageException in the first place.

Code could be something like this:

private String FindFaultedQueue() {
   ServiceHostBase host = OperationContext.Current.Host;
   Uri faultedQueue = null;
   // the queue that fired the exception will be the faulted one
   foreach ( ChannelDispatcher chd in host.ChannelDispatchers ) {
      if ( chd.State == CommunicationState.Faulted ) {
         faultedQueue = chd.Listener.Uri;
      }
   }
   // translate URI into a regular MSMQ format name 
   StringBuilder fn = new StringBuilder("FormatName:DIRECT=OS:");
   fn.Append(faultedQueue.Host).Append("\\");
   string path = faultedQueue.PathAndQuery;
   if ( path.StartsWith("/private/") ) {
      fn.Append("private$\\");
      path = path.Substring("/private".Length);
   }
   path = path.Substring(1);
   fn.Append(path);
   return fn.ToString();
}

This lacks some error handling and a few other things, but it illustrates the point. Now that we have the FormatName of the queue where the poison message came from, we can try to move it to the poison message  queue. We could handle this by convention: for queue Q1, the corresponding poison message queue could be Q1Poison. The rest of the sample is pretty much the same.

I probably wouldn't use this in production, as it doesn't feel very reliable given the basic limitations imposed by the WCF implementation, but it was interesting to take a stab at. YMMV.

[1] I'll leave to you, dear reader, to wonder about the sense of providing a sample that so clearly points out such a giant hole in a product feature rather than actually fixing it. Oh wait, guess they did fix it by changing MSMQ for Vista and WinServer2k8.

Filenames Starting with a Dot

Link. February 25, 2008. Comments [8]. Posted in: Vista

In Unix, it's common to name files and folders with names starting with a '.' to make them "hidden". This convention is not really needed in Windows, since there's a file system attribute for that, but still interesting.

See, a few tools ported from Unix that relied on this convention use a different one in Windows, replacing the '.' with a '_'. So, for example, your Vim settings file will be "_vimrc" instead of ".vimrc" and so on. Seems pretty obvious they did this because at some point in time file/folder names could not start with a dot.

Windows 9x probably had this limitation, and probably still lives on in FAT-based file systems (but I don't have one anywhere to test this assertion, nor do I particularly care about it). However, modern Windows and NTFS have no such limitation. Almost.

See, NTFS certainly let's you create a folder named ".vimfiles" or a file named ".txt" for that matter. You can do so programatically using the standard file handling APIs. You can do it from the command line using mkdir/echo.

But you can't do it using Windows Explorer. For example, Vista and WinServer2k8 will complain that "You must type a filename" if you attempt to name a folder/file with a dot as the first character in the name.

Why Explorer explicitly disallows it, I'm not sure, but seems pretty funky. There are probably thousands of applications or utilities out there that might get confused with a file or folder named like that, though.

Can't Remove Drive on Vista SP1

Link. February 24, 2008. Comments [0]. Posted in: Vista

I haven't noticed many issues with Vista SP1, despite some stuff I've read around; though overall haven't really noticed any significant performance difference besides file operations using Windows Explorer.

That said, I've noticed one nasty issue: I use an external USB drive that has a bunch of virtual machines, my music and other stuff. I'm usually very careful and always use the "Safely Remove Hardware" icon in the system tray to remove the drive before disconnecting it from the computer or turning it off.

However, ever since installing SP1, this operation fails about 50% of the time, saying the volume is in use and cannot be removed, even though there are no applications open that could be using the drive at all.

The past few times it's happened, I've fired up Process Explorer to try and locate what is holding on to the drive, only to find that the only process that has file handles opened in the drive is the "System" pseudo-process:

EjectDrive

No idea which driver is holding on to the handles, but based on the file names, I might guess it has something to do with the Kernel transaction manager and NTFS transactions. Why those handles are being kept there, I have no idea; but once this happens, those don't get released, meaning I have to shut down the drive improperly. Not good.

Simple Is Beautiful

Link. February 21, 2008. Comments [3]. Posted in: Vista
WinServer2k8

Am I the only one that thinks the Windows Server 2008 logon screen, with it's very simple blue background, is so much better looking that Vista's ugly and distracting "aurora" background?

There's just something highly appealing to me about keeping things simple and elegant...

About

Tomas Restrepo is co-founder of devdeo. His interests include .NET, Connected Systems, PowerShell and, lately, dynamic programming languages. More...

email: tomas@winterdom.com
msn: tomasr@passport.com
twitter: tomas_restrepo

Technorati Profile

devdeo logo

View my profile on LinkedIn

MVP logo

Syndicate

Ads


Links

Categories

Statistics

Total Posts: 1006
This Year: 76
This Month: 7
This Week: 0
Comments: 771

Blogroll

Post Archive

Other

Copyright © 2002-2008, Tomas Restrepo.

Powered by: newtelligence dasBlog 1.9.7174.0

Sign In