Monthly Archives: July 2008

Where is my Desktop?

DesktopProperties

 

Some people tend to save their documents and files on a separate drive.  This allows the flexibility of flattening the Windows/OS partition at any time, without losing any data.  This is one reason I have never been a fan of using the %USERPROFILE% folders (eg. C:Users<UserName> on Vista or C:Documents and Settings<UserName> on XP).

It turns out, though, that you can redirect these ‘special’ shell folders easily on Vista, or with the Tweak UI PowerToy for XP (or hacking up the registry).  These folders include things like “My Pictures,” “My Music,” “Favorites,” or even your “Desktop” folder.  On Vista, for instance, when you right-click the Desktop folder and select Properties, you get the dialog on the right.

If you’ve done this, obviously it’s not good enough to assume that your desktop is in %USERPROFILE%Desktop.  You’ve got to open up the registry to find the location of these “User Shell Folders”:

set OUTPUTDIR=%USERPROFILE%Desktop

set SHFOLDER_REGISTRY_KEY = "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell Folders"
for /f "tokens=2*" %%i in (
    ‘REG QUERY %SHFOLDER_REGISTRY_KEY% /v Desktop’
) do (
    call set OUTPUTDIR=%%~j
)

Notes:

  • We’re querying HKCU, so no elevation on Vista is required.
  • Most of values underneath this key are of type REG_EXPAND_SZ.  This is why we need to ‘call’ to expand the value.
  • Bonus points if you can tell me why I start with token #2.

In some cases, you may also find that there is a “DesktopDirectory” value as well as a “Desktop” value underneath that key.  I cannot eloquently explain the difference, but perhaps you may be able to interpret Wikipedia’s explanation:

The "Desktop" virtual folder is not the same thing as the "Desktop" special folder. The Desktop virtual folder is the root of the Windows Shell namespace, which contains other virtual folders.

I believe that DesktopDirectory is the correct value to use, but sometimes it is not available.  Most of the time the two values are equivalent.

I bet you someone on the shell team could explain this properly, if he hasn’t already.  I’m sure there’s an interesting story behind it.

Extension Methods and LINQ

I know very little about the new features of C# 3.0 and LINQ.  I’ve been playing around with it a little bit and was puzzled by how it all works.  This is probably old news for a lot of people, but it’s all new to me.  For instance, let’s take the simplest possible query:

int[] numbers = { 4, 8, 15, 16, 23, 42 };
var query = from n in numbers where IsPrime(n) select n;

Trying to compile, I got this compiler error:

Error: Could not find an implementation of the query pattern for source type ‘int[]’.  ‘Where’ not found.  Are you missing a reference to ‘System.Core.dll’ or a using directive for ‘System.Linq’?

You might get this error if you’re missing some references (as the error message says).  I was getting it due to some other external issue.  But in trying to fix/investigate the issue, I first tried to figure out what exactly the compiler was doing behind the scenes.  The method ‘Where’ isn’t available on IEnumerable or Array, so it seemed like a valid error.  What was I missing?

I couldn’t find any good information online as to how the compiler actually takes the LINQ syntax and generates code that resembles something more IL-ish.  There are plenty of sample queries online, but I couldn’t find any good site that really explains how it all works.  So after a bunch of digging I managed to piece together that the compiler actually translates the above query to something like this:

var query = numbers.AsQueryable().Where(n => n.IsPrime());

Interesting.  That kind of explains where the error message is coming from.  But still, I couldn’t for the life of me figure out how the heck this worked.  There’s no ‘AsQueryable’ method on Array or IEnumerable, or ‘Where’ on IQueryable either.  Where are these methods coming from?

It turns out that the compiler further translates the query to something like this:

IQueryable<int> query = Queryable.Where<int>(Queryable.AsQueryable(numbers), delegate(int n) { return IsPrime(n); });

How the heck?!  Where did the Queryable class come from?

Apparently there is this new concept of “extension methods” in C#.  You can add methods to existing types without creating a new derived type, or recompiling, or modifying the original type.  Wow!!  Far out!

System.Linq has a static class ‘Queryable’ that does exactly this; it extends IEnumerable and IQueryable<T>.

public static IQueryable AsQueryable(this IEnumerable source);
public static
IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate);

All you have to do is add the directive “using System.Linq;” to take advantage of this functionality.  Check out the rules on how to implement a custom extension method.

And now it all makes sense.  Very cool!