Loren Halvorson's Blog

If your only tool is a hammer...

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, "");
}

Comments

Gary said:

In one of your previous blogs, you mentioned about ibd files and how to extract them using orca. What do you do if you want to create these ibd files, say from a jpeg or icon file. Thanks!
# November 4, 2004 6:05 AM

Lorenh said:

The "ibd" file extension stands for "Installer binary data", and I'm pretty sure they are just renamed JPEG files.
# November 4, 2004 10:17 AM

TrackBack said:

# March 9, 2005 6:09 PM

Matt said:

Hey Loren,

Do you still use this? Looks like a very useful script!

Cheers,

Matt

# August 16, 2007 6:50 AM