Tips and Tricks: Installing Programs to a USB Key

My laptop is rapidly becoming obsolete, particularly when it comes to disk space :(.  I want to install my games on it, so I have something to do in class between classes, but I’m running out space.  So, I came up with an idea: Buy a 16GB USB Key, and put a bunch of games on that!  I keep my USB keys in my backpack, so they’re never too far away.  It sounded like the perfect solution, until I noticed that many programs can’t be installed on Removable Drives!

So, I came up with a simple workaround, once again using an awesome tool from Sysinternals :).  I used Junction to create a junction folder called “C:\Program Files\Games” which points to a “Games” folder on my USB Key.  The following command line does the trick (assuming F:\Games is the folder on the USB key, and it already exists):

junction.exe “C:\Program Files\Games” “F:\Games”

Seems to be working so far!  I just install the game into that folder, and all the files go to the USB Key.  Of course, its not quite the same as a portable app, since it will only run on the machine it was installed on, but it takes some of the burden off of my hard drive.  If my laptop supported SDHC, I’d probably use a 16GB SD card and just leave it plugged in to my laptop, but unfortunately, that’s not an option.

Tips and Tricks: Remotely Enable Remote Desktop

Before I start this post, I need to say one thing: Mark Russinovich (as well as anyone else who works on the Sysinternals stuff) is a Windows Magician.  The stuff these tools can do is just plan magic :).

Last week, my Dad’s Dell XPS laptop decided it was tired of rendering graphics and the video card just stopped working (apparently this is a known issue).  Dell support was fairly helpful and on Friday we received a box to sent the computer in for a motherboard replacement.  Now, I’m paranoid when it comes to data, I don’t trust anyone.  So, I suggested we try and wipe the hard drive of all the sensitive data on the machine, and change the password so that we wouldn’t have to give Dell the actual password.  Now, only the graphics card was damaged, the computer ran just fine and even the graphics were intermittent (at first).  We tried to get the graphics card working long enough to enable remote desktop, so we could connect from his screaming new Dell desktop (Quad Core i7 with 12GB of RAM… I’m jealous).  Unfortunately, by that time, the graphics card was done… no dice :(

After a little searching, I came across some tips for enabling remote desktop… remotely.  It turns out, there are a number of ways to connect to a machine and make changes remotely!  The first tip I found was to use the remote registry to enable it: http://www.windowsdevcenter.com/pub/a/windows/2004/05/04/serverhacks_remote.html.  Unfortunately, the Remote Registry service wasn’t running on the laptop!  That’s when I found Sysinternals “PsService” tool.  The tool allows you, as long as you have the Admin account password, to enable/disable and change the start mode of services on a remote machine.  So, first I enabled to remote registry service

psservice \\bilbo –u [UserName] start RemoteRegistry

Then, just for good measure, I set the Remote Desktop service to autostart

psservice \\bilbo –u [UserName] setconfig TermService auto

Finally, rather than fight with creating a firewall rule remotely, I just disabled the Windows Firewall service (don’t do this unless you absolutely have to :D)

psservice \\bilbo –u [UserName] setconfig MpsSvc disabled

(Btw, I got all these service names using the Services console on another machine)

Finally, I followed the instructions I mentioned earlier to set the right registry flags to allow Remote Desktop.  I killed the power to the PC (I actually tried Sysinternals “PsShutdown” tool first, but had less luck getting that working :D) and restarted it.  When I heard the Windows start up sound (as I said, the rest of the components worked just fine :), I fired up remote desktop connection and… bam!  I had a remote desktop screen.  After a quick pass over the data drive with yet another Sysinternals tool: “SDelete” and a password change, we shut the computer down, packed it up and sent it off to Dell, confident that the important data was scrubbed clean.

Like I said… black magic :).  But seriously, the Sysinternals tools rock!  If you don’t have them, get them now!

Argument check gotcha with ‘yield’ keyword in C#

I recently used the ‘yield’ keyword in a C# method and ran into a strange issue when trying to verify arguments.  I always try to verify the arguments provided to my methods so that I can throw ArgumentException or ArgumentNullException as necessary.  However, when you use the ‘yield’ keyword to create an enumerator in C#, you can run into issues

The ‘yield’ keyword lets you easily create a method which returns an enumerator (which can then be used in a foreach loop).  For example, if I wanted to make a method that took a DirectoryInfo (representing a directory on disk) and returned file names of all the .txt files in it, I would write this:

public IEnumerable<string> GetTextFiles(DirectoryInfo dir) {
    if (dir == null) {
        throw new ArgumentNullException("dir");
    }
    foreach (FileInfo file in dir.GetFiles("*.txt")) {
        yield return file.Name;
    }
}

However, the C# compiler will do something tricky with this method, because of the 'yield' keyword.  It will create a custom implementation of IEnumerable<string> class that uses "magic" (I'm not going to go into detail as to how it works :P) to jump in and out of the code you wrote. Then, it compiles our method to the following (as decompiled with RedGate's .Net Reflector, a free tool every .Net developer must have :D):

public IEnumerable<string> GetTextFiles(DirectoryInfo dir)
{
    <GetTextFiles>d__0 d__ = new <GetTextFiles<d__0(-2);
    d__.<>4__this = this;
    d__.<>3__dir = dir;
    return d__;
}

Wait a sec, where'd our code go?  It looks like it’s gone into this <GetTextFiles>d__0 class.  If you think that name sounds compiler-generated, you’re right!  It’s the custom implementation of IEnumerable<string> that was created by the compiler.  Cool, eh?  However, there’s a side effect here.  Where did our argument checking code go?  Unless there’s something in the <GetTextFiles>d__0 constructor, the user could pass null in for the dir parameter and no exception would be thrown!  So, let’s take a look at the <GetTextFiles>d__0 constructor (using Reflector again):

[DebuggerHidden]
public <GetTextFiles>d__0(int <>1__state)
{
    this.<>1__state = <>1__state;
    this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}

Nope, nothing there.  If you keep checking around the <GetTextFiles>d__0 class, you’ll find it in the MoveNext method on that class.  That means that instead of checking the argument when you call the method, the argument won’t be checked until the first time MoveNext is called (i.e. the first iteration of a foreach loop).  If, instead, we wrap the actual “yield” code in it’s own method, and call it from our original method (after argument checks), we’ll get the desired result:

public IEnumerable<string> GetTextFiles(DirectoryInfo dir) {
    if (dir == null) {
        throw new ArgumentNullException("dir");
    }
    return InternalGetTextFiles(dir);
}
private IEnumerable<string> InternalGetTextFiles(DirectoryInfor dir) {
    foreach (FileInfo file in dir.GetFiles("*.txt")) {
        yield return file.Name;
    }
}

Now, the "magic" is occurring in InternalGetTextFiles and GetTextFiles is compiled without modification and our argument checking works just fine.

Wild Ideas – Using lambdas to check arguments in C#

One of the most common checks I do is a simple null check on arguments being passed in to the methods I write.  I usually create a static class called “Arg” with the following methods (to help out):

public static class Arg {
    public static void NotNull(object value, string paramName) {
        if (value == null) {
            throw new ArgumentNullException(paramName);
        }
    }
    public static void NotNullOrEmpty(string value, string paramName) {
        if (String.IsNullOrEmpty(value)) {
            // ED: Error_StringArgumentNullOrEmpty is a key in my Visual Studio
            //  project's default string resources file (Properties/Resources.resx)
            throw new ArgumentException(
                String.Format(CultureInfo.CurrentCulture, 
                              Resources.Error_StringArgumentNullOrEmpty, 
                              paramName), 
                paramName);
        }
    }
}

Then, I can use it like this

public void Foo(string arg, object reallyLongArgumentName) {
    Arg.NotNullOrEmpty(arg, "arg");
    Arg.NotNull(reallyLongArgumentName, "reallyLongArgumentName");
}

I was recently playing with lambda expressions in C# and thought of a way to make this a little cooler.  The result is, I can rewrite the lines above like this:

public void Foo(string arg, object reallyLongArgumentName) {
    Arg.NotNullOrEmpty(() => arg);
    Arg.NotNull(() => reallyLongArgumentName);
}

The first obvious advantage is that for longer argument names, its more concise.  The second, is that I no longer have to worry about updating the strings representing the parameter names when I rename arguments, the Visual Studio Refactoring engine will take care of it for me.

Obviously, this is slower than the previous method since I’m diving into the lambda expression at runtime, but its cool.  But if I need the performance, I have a little Regular Expression I can run in Visual Studio to convert the lambda calls back to the string versions (and vice-versa)

How does it work? Well, the core of the code is a static helper in the Arg class

private static string GetParameterName<T>(Expression<Func<T>> paramExpr) {
    LambdaExpression lambda = paramExpr as LambdaExpression;
    Debug.Assert(lambda != null);
    MemberExpression paramRef = lambda.Body as MemberExpression;
    Debug.Assert(paramRef != null);

    // Get the parameter name
    string paramName = paramRef.Member.Name;
    return paramName;
}

Lines 2-5 dive through the Expression tree to find the MemberExpression that represents the parameter (i.e. "foo" in () => foo). Then, we pull out the MemberInfo for the parameter and check the name. With that method, the actual checker is easy:

public static void NotNull(Expression<Func<object>> paramExpr) {
    string paramName = GetParameterName(paramExpr);

    // Compile the lambda (to get the value)
    Func<object> compiledLambda = paramExpr.Compile();
    
    // Run the contract check
    NotNull(compiledLambda(), paramName);
}

Line 2 extracts the parameter name. Line 5 compiles the lambda into an actual function that will return the value of the parameter. Finally, Line 8 uses the value and the parameter name to call my original object/string version. The code for NotNullOrEmpty is nearly identical.

Anyway, if you're concerned about performance, stick to the overloads which take the parameter name directly. I’ve attached the code as a TXT file, just rename to C#, change the namespace as appropriate and enjoy

Arg.txt (3.93 KB)

Redirecting your Zune Library to another folder/drive

As I mentioned in an earlier post about backing up a Zune Library (Backup a Zune Library...), I wanted to find a way to be able to actually store the Zune library database on a different drive.  I played with the Microsoft Sysinternals “Junction” tool, which lets you create hardlinks (Wikipedia on Hardlinks) and managed to get it to work.  Here’s the process to do it yourself.  Replace UserName with your Windows user name and D:\Music\Zune\Library with the path to the folder you want to store the database in.

  1. Download Junction.exe from here: http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx (replace D:\Utils\Sysinternals\junction.exe below with the path you downloaded junction.exe to)
  2. Shut down the Zune software if it is running.
  3. Rename the folder C:\Users\UserName\AppData\Local\Microsoft\Zune to Zune_backup (just to be safe).  You may encounter a file locking issue, but I found that if I waited a few minutes it worked.
  4. Copy the Zune_backup folder to D:\Music\Zune and rename it to Library
  5. Run the following command:
    D:\Utils\Sysinternals\junction.exe Zune D:\Music\Zune\Library

That should do it!  Start Zune up again and your library should be up and running.  Now you should be able to reinstall the OS without having to back up the Zune library.  I might try to whip up a PowerShell or Batch file to do this, but don’t get too hopeful :).

Backing up a Zune Library for when you reinstall Windows

I regularly reinstall Windows, so when I used iTunes, I had to make sure I knew how to back up my music library (because I didn't want to re-rate all my songs :D).  I recently switched back to Zune from iTunes because I got so frustrated with my cracked iPod Touch screen.  Then, came the invevitable reinstall :)

I keep my music on a separate partition, along with ALL my data (Folder Redirection for the win!), so the music files aren't the problem.  With iTunes I could place the music library database on the other drive too, but so far no luck there with the Zune software (I'm going to check out Junctions to see if that will work).  So, I resigned myself to digging through my AppData folder to see if I could find the stuff I needed.

For those who don't already know, the AppData folder, in Windows Vista is in: C:\Users\[UserName]\AppData.  This is where programs (should) store their per-user settings and configuration data.  Unfortunately (AFAIK) it's not possible to redirect this folder (like you can with Documents, Music, etc.). 

The Zune software stores its settings in C:\Users\[UserName]\AppData\Local\Microsoft\Zune.  All I had to do was copy this folder over to my second partition, reinstall the OS and reinstall the Zune software.  Then, I started the Zune software, just to be sure and shut it down again.  I copied the backed up folder back into place, restarted the Zune software and voila my library is back.  I was even able to reconnect my Zune and have it automatically recognize it and sync!

So, in summary:
  1. Back up C:\Users\[UserName]\AppData\Local\Microsoft\Zune
  2. Reinstall Windows and other Apps
  3. Reinstall Zune
  4. Start Zune software (not sure if it's necessary, but it worked for me)
  5. Shutdown Zune software
  6. Copy backup back in to C:\Users\[UserName]\AppData\Local\Microsoft\Zune
  7. Start Zune software and enjoy!
Let me know if that works for you, or if you have problems!