DevelopmentOpen SourceXRap

WiX – Listing File System in XML

By October 17, 2008August 21st, 20132 Comments

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

2 Comments

  • How do you ensure that the Component/@Guid’s don’t break the Component Rules?

  • Joshua says:

    The .NET Framework provides a Guid structure, which can create a unique guid, then just send it to toString().toUpper() to make it an upper case string so I can add it as an attribute of Component.

    Here’s the call:
    Guid.NewGuid().ToString().ToUpper()

    I just did it in the setAttribute method of the XmlElement:
    xeCom.SetAttribute(”Guid”, Guid.NewGuid().ToString().ToUpper());

    The Guid’s are supposed to be completely unique, do you know any other rules for Component?

Leave a Reply to Joshua Cancel Reply