Using Nant for Metabase backup on 64bit Windows Server 2003

January 28, 2009 at 4:26 PMAndre Loker

For while now I’ve been using NAnt not only as a build tool but also as the tool running all my backup tasks, such as:

  • database backups
  • Subversion repository backups
  • mail backup
  • website backup

I’ve also used it to create backups of the IIS Metabase using the iisback.vbs script, which works perfectly smooth as long as it is running on a 32 bit Windows.

I’ve been trying to backup the IIS Metabase on a 64 bit Windows Server 2003 server for a while now, but for some reasons I could not make it work. If I tried to call the script directly using the commandline, e.g.

   1: iisback.vbs /backup /s localhost /e something /v NEXT_VERSION 
   2:       /b Metabase123 //E:vbscript

it would ran perfectly fine. However, when executed as a NAnt task I got an error:

Could not create an instance of the CmdLib object.
Please register the Microsoft.CmdLib component.

After digging in the dark for a while I found an interesting forum thread of somebody with a similar problem. So I more or less did what has been proposed in that thread:

  1. I copied cmdlib.wsc over from %WINDIR%\System32 to %WINDIR%\SysWOW64
  2. I also copied isschlp.wsc the same way
  3. I registered cmdlib.wsc and isschlp.wsc using regsvr32 cmdlib.wsc and regsvr32 isschlp.wsc respectively

At that point my NAnt script was happy again and created the backups.

The reason and more trouble

As far as I understand the problem was that NAnt is for some reason running as a 32 bit application. On 64bit Windows boxes, the System32 folder contains the 64bit binaries whereas the SysWOW64 folder contains the 32bit versions. Frankly, this is not the most intuitive naming ever, but it has a reason. If a 32 bit application is running the System32 folder becomes an alias for the SysWOW64 folder, with the effect that for 32 bit applications, Windows looks totally normal (ie. 32 bit). However, this also means that binaries that are found in the unaliased System32 folder are not accessible for 32 bit application. Hence the need to copy and reregister cmdlib.wsc and isshlp.wsc.

Now that I had this one working I directly faced a second problem: the backups of the metabase are stored at %WINDIR%\System32\inetserv\MetaBack. I think you can guess what’s the problem: the folder is hidden for 32 bit applications, which means that I can’t copy the Metabase backups using NAnt, because NAnt only sees the aliased version of System32.

So here’s what I did to solve this issue: I couldn’t find a way to disable the file system aliasing though standard means in NAnt, but I found an API that could help me:

Using the first of those two method disables the aliasing for the current thread. So I wrote a small C# program that first disables the aliasing (by P/Invoking the methods mentioned above) and then copies the backed up files out of the System32 folder into a conventional folder. I could then continue to use NAnt to further process those files (e.g. zipping them, mailing them somewhere – whatever).

Here’s the code of the class that disables/reverts the file system aliasing:

   1: /// <summary>
   2: /// Disables file system aliasing for 32 bit applications
   3: /// on 64 bit systems.
   4: /// </summary>
   5: public class DisableWow64Redirect : IDisposable {
   6:   #region P/invoke
   7:   [DllImport("Kernel32")]
   8:   private static extern bool Wow64DisableWow64FsRedirection(out IntPtr oldValue);
   9:  
  10:   [DllImport("Kernel32")]
  11:   private static extern bool Wow64RevertWow64FsRedirection(IntPtr oldValue)
  12:   #endregion
  13:  
  14:   private readonly IntPtr oldValue;
  15:  
  16:   /// <summary>
  17:   /// Creating a new object disables file system aliasing for the current thread.
  18:   /// </summary>
  19:   /// <remarks>
  20:   /// Use <see cref="Dispose"/> to re-enable file system aliasing.</remarks>
  21:   public DisableWow64Redirect() {
  22:     Success = Wow64DisableWow64FsRedirection(out oldValue);
  23:   }
  24:  
  25:   public bool Success { get; private set; }
  26:  
  27:   /// <summary>
  28:   /// Disposes this object and reenables the file system aliasing.
  29:   /// </summary>
  30:   public void Dispose() {
  31:     if (Success) {
  32:       Success = Wow64RevertWow64FsRedirection(oldValue);
  33:     }
  34:   }
  35: }

Granted, this is probably not the best solution one could think of, but it works for me for the moment. If anyone has a better idea, let me know!

 

Posted in: Windows | Snippets | C#

Tags: , ,

Pingbacks and trackbacks (1)+