Field Notes from the Workshop · № 114 Development

WiX – Listing File System in XML

Joshua Doodnauth Software Engineer · Toronto
October 17, 2008 2 min read 392 words

Problem:

WiX uses an XML file for instructions on what directories to add to the msi package.  I had no problem in recursively going through the source directory and pulling all sub-directories and files, the trouble I have is inserting those entries into an XML file with the same depth as in the file system.

Working Solution:

After over a week of doing build, run and repeat, I figured I should use the stack in C#, eureka!  Before I was bouncing around some methods until I got all files and directories out, the good things was that they came out in order, the bad thing was that it got complicated because I was passing too many parameters, an XMLELEMENT, XMLDOCUMENT, the directory to read, and then I couldn’t attach a sub-directory to a directory, because it thinks the directory hasn’t been created yet.  Ahh, what a mess.

I implemented the stack in a while loop, pushed directories on it, and at the same time read the directory on the top of the stack for files.  It’s a little complicated when looking at how the directories are read, but I realized it was backwards, because it has the last directory added on the top of the stack.

XmlElement xeDir;
dirStack.Push(args[0]);
int dirCount = -1;
int uniqueFile = 0;
while (dirStack.Count > 0)
{
String curDir = dirStack.Pop(); 

if (dirCount == dirStack.Count)
{
XmlElement childDir = xmlDoc.CreateElement(“Directory”);
childDir.SetAttribute(“Id”, curDir);
Console.WriteLine(“NODE:” +installDirNode.ChildNodes.Count);
installDirNode.LastChild.AppendChild(childDir);

foreach (String fileName in Directory.GetFiles(curDir, “*.*”))
{
String[] comFileID = fileName.Split(new char[] { ‘\\’ });
String[] comID = comFileID[comFileID.Length-1].Split(new char[] { ‘.’ });

XmlElement xeCom = xmlDoc.CreateElement(“Component”);
xeCom.SetAttribute(“Id”, comID[comID.Length-2] + uniqueFile);
xeCom.SetAttribute(“Guid”, Guid.NewGuid().ToString().ToUpper());

XmlElement xeFile = xmlDoc.CreateElement(“File”);
xeFile.SetAttribute(“Id”, fileName);
childDir.AppendChild(xeCom);
xeCom.AppendChild(xeFile);
fileReturn.Add(fileName);
uniqueFile++;
}
}
else
{
xeDir = xmlDoc.CreateElement(“Directory”);
xeDir.SetAttribute(“Id”, curDir);
installDirNode.AppendChild(xeDir);

foreach (String fileName in Directory.GetFiles(curDir, “*.*”))
{
XmlElement xeFile = xmlDoc.CreateElement(“File”);
xeFile.SetAttribute(“Id”, fileName);
xeDir.AppendChild(xeFile);
fileReturn.Add(fileName);
}
}
dirCount = dirStack.Count;
foreach(String dirName in Directory.GetDirectories(curDir))
{
dirStack.Push(dirName);
}
}

Current Problem:

I am able to attach sub-directories to the parent directory in the XML file, but if there is another sub-directory below the first sub-directory, I can’t attach it that deep.

SOLVED! My Solution