Loren Halvorson's Blog

If your only tool is a hammer...

October 2004 - Posts

Updated WiX generation script

This is long overdue, but I finally sat down and tweaked the script I provided in WiX for dummies post so it no longer uses FileGroup. This walks through a tree and generates a component for every file. The FileGroup element now appears to have been removed from WiX rather than just deprecated, so if any of you followed the steps in the original post, you'll need this when you update to a newer build of WiX. Another approach is to use Tallow.exe, but I haven't played with it enough to say how.

--- generate-install-script.js ---

// Generates the WiX XML necessary to install a directory tree.
var g_shell = new ActiveXObject("WScript.Shell");
var g_fs = new ActiveXObject("Scripting.FileSystemObject");
if (WScript.Arguments.length != 2)
{
 WScript.Echo("Usage: cscript.exe generate-install-script.js <rootFolder> <outputXMLFile>");
 WScript.Quit(1);
}
var rootDir = WScript.Arguments.Item(0);
var outFile = WScript.Arguments.Item(1);
var baseFolder = g_fs.GetFolder(rootDir);
var componentIds = new Array();

WScript.Echo("Generating " + outFile + "...");

var f = g_fs.CreateTextFile(outFile, true);
f.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
f.WriteLine("<Include>");
f.WriteLine("  <Directory Id=\"TARGETDIR\" Name=\"SourceDir\">");
f.Write(getDirTree(rootDir, "", 1, baseFolder, componentIds));
f.WriteLine("  </Directory>");
f.WriteLine("  <Feature Id=\"DefaultFeature\" Level=\"1\" ConfigurableDirectory=\"TARGETDIR\">");
for (var i=0; i<componentIds.length; i++)
{
 f.WriteLine("    <ComponentRef Id=\"C__" + componentIds[i] + "\" />");
}
f.WriteLine("  </Feature>");
f.WriteLine("</Include>");
f.Close();

// recursive method to extract information for a folder
function getDirTree(root, xml, indent, baseFolder, componentIds)
{
 var fdrFolder = null;
 try
 {
  fdrFolder = g_fs.GetFolder(root);
 }
 catch (e)
 {
  return;
 }

 // indent the xml
 var space = "";
 for (var i=0; i<indent; i++)
  space = space + "  ";

 if (fdrFolder != baseFolder)
 {
  var directoryId = "_" + FlatFormat(GetGuid());

  xml = xml + space + "<Directory Id=\"" + directoryId +"\"";
  xml = xml + " Name=\"" + fdrFolder.ShortName.toUpperCase() + "\"";
  xml = xml + " LongName=\"" + fdrFolder.Name + "\">\r\n";
 }

 var componentGuid = GetGuid();
 var componentId = FlatFormat(componentGuid);


 xml = xml + space + "  <Component Id=\"C__" + componentId + "\""
     + " Guid=\"" + componentGuid + "\">\r\n";

 if (fdrFolder.Files.Count > 0)
 {
  var enumFiles = new Enumerator(fdrFolder.Files);

  for (;!enumFiles.atEnd();enumFiles.moveNext())
  {

   var file = enumFiles.item();

   var fId = "_" + FlatFormat(GetGuid());
   xml = xml + space + "    <File Id=\"" + fId +
            "\" Name=\"" + file.ShortName.toUpperCase() +
            "\" LongName=\"" + file.Name +
            "\" src=\"$(var.redist_folder)" + file.Path.substring(baseFolder.Path.length) +
            "\" Vital=\"yes" +
            "\" DiskId=\"1\"/>\r\n";
  }
 }
 else
 {
  xml = xml + space + "    <CreateFolder />\r\n";
 }

 xml = xml + space + "  </Component>\r\n";

 componentIds[componentIds.length] = componentId;


 var enumSubFolders = new Enumerator(fdrFolder.SubFolders);

 var depth = indent + 1;
 for (;!enumSubFolders.atEnd();enumSubFolders.moveNext())
 {
  var subfolder = enumSubFolders.item();
  xml = getDirTree(enumSubFolders.item().Path, xml, depth, baseFolder, componentIds);
 }

 if (fdrFolder != baseFolder)
 {
  xml = xml + space + "</Directory>\r\n";
 }

 return xml;
}

// Generate a new GUID
function GetGuid()
{
 return new ActiveXObject("Scriptlet.Typelib").Guid.substr(1,36).toUpperCase();
}

// Convert a GUID from this format
//   7E70E5E5-CE19-4270-A740-223A09796433
// to this format:
//   7E70E5E5CE194270A740223A09796433
function FlatFormat(guid)
{
 return guid.replace(/-/g, "");
}

Media Center 2005 and Extender
After a couple of years of talking about it (as my friends will attest) I finally ordered a new PC with the recently released Windows Media Center Edition 2005 for the den, and a Linksys Media Center Extender for the living room. I've only had it set up for a couple of days, but so far I think it's great. The extender is a TV set-top box that allows you to access most of the Media Center features from the TV via a remote. For some time now, I've been interested in getting a Tivo/DVR for my wife who is always missing her favorite shows because she forgets to stick a tape into the VHS recorder and program it to tape. Additionally since we home-school our kids, we figured it would be handy to record educational shows for them. I was hesitant to get a Tivo because of the monthly subscription charge and limited recording capacity. Now I have the DVR functionality, plus the ability to view my digital pictures, listen to my music collection, and more, with no monthly subscription. I needed to replace my old PC anyway, so this was ideal for me. I don't think many people know about the Extenders, I just wanted to spread the word that they are shipping, and they are a great solution for those who want to access their Media Center features from different rooms in your house. I'm looking into buying a couple more extenders for other TVs in the house. Maybe the $79 kit that converts an Xbox into a Media Center Extender will finally get me to buy an Xbox for the "educational" value :-).
More Posts