[转]-Harvesting wix files

Harvesting wix files

Back | wix | 4/14/2010 | Tweet

Sometimes great is the enemy of good. I recently had to harvest a large number of files to create a wix installer. I tried heat.exe, but after struggling with its generation style and even considering writing an XSLT, I decided it would be faster to just code what I want in C#. This generates a .wxi file that follows somewhat of a standard of naming components .C, directories .D and skipping .svn folders.

It just gets the job done.

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
 
namespace HarvestingWixFiles
{
 class Program
    {
 static string MakeId(string id)
        {
 return id.Replace("_", ".").Replace("-", ".");
        }
 
 const String wixns = "http://schemas.microsoft.com/wix/2006/wi";
 
 static List<String> GenerateFragment(XmlDocument doc, XmlNode parent, DirectoryInfo dir, DirectoryInfo root)
        {
            List<String> componentIds = new List<string>();
 
            XmlNode directory = (doc.FirstChild == parent)
                ? parent.AppendChild(doc.CreateElement("DirectoryRef", wixns))
                : parent.AppendChild(doc.CreateElement("Directory", wixns));
 
 string id = "";
 if (parent.Attributes["Id"] != null) 
                id = parent.Attributes["Id"].Value.Replace(".D", "") + ".";
            id += dir.Name + ".D";
 
            directory.Attributes.Append(doc.CreateAttribute("Id")).Value = MakeId(id);
 if (doc.FirstChild != parent)
            {
                directory.Attributes.Append(doc.CreateAttribute("Name")).Value = dir.Name;
            }
 
            FileInfo[] files = dir.GetFiles();
            List<DirectoryInfo> subdirs = new List<DirectoryInfo>(dir.GetDirectories());
 for (int i = subdirs.Count - 1; i >= 0; i--)
            {
 if (subdirs[i].Name == ".svn")
                {
                    subdirs.RemoveAt(i);
                }
            }
 
 if (files.Length == 0 && subdirs.Count == 0)
            {
                XmlNode component = directory.AppendChild(doc.CreateElement("Component", wixns));
 string componentId = id.Replace(".D", ".") + "C";
                componentIds.Add(componentId);
                component.Attributes.Append(doc.CreateAttribute("Id")).Value = MakeId(componentId);
                component.Attributes.Append(doc.CreateAttribute("Guid")).Value = Guid.NewGuid().ToString();
                component.AppendChild(doc.CreateElement("CreateFolder", wixns));
            }
 else if (files.Length > 0)
            {
                XmlNode component = directory.AppendChild(doc.CreateElement("Component", wixns));
 string componentId = id.Replace(".D", ".") + "C";
                componentIds.Add(componentId);
                component.Attributes.Append(doc.CreateAttribute("Id")).Value = MakeId(componentId);
                component.Attributes.Append(doc.CreateAttribute("Guid")).Value = Guid.NewGuid().ToString();
 foreach (FileInfo file in files)
                {
                    XmlNode node = component.AppendChild(doc.CreateElement("File", wixns));
                    node.Attributes.Append(doc.CreateAttribute("Id")).Value = MakeId(id.Replace(".D", ".") + file.Name);
                    node.Attributes.Append(doc.CreateAttribute("Source")).Value =
 "$(var." + Path.GetFileName(root.FullName) + "Dir)\" +
                        file.FullName.Substring(root.FullName.Length).TrimStart('\');
                }
            }
 
            foreach (DirectoryInfo subdir in subdirs)
            {
                componentIds.AddRange(GenerateFragment(doc, directory, subdir, root));
            }
 
            return componentIds;
        }
 
        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0)
                {
                    throw new ArgumentException("Missing dir");
                }
 
                XmlDocument doc = new XmlDocument();
                doc.LoadXml("<Include xmlns="http://schemas.microsoft.com/wix/2006/wi" />");
                DirectoryInfo root = new DirectoryInfo(args[0]);
                List<String> componentIds = GenerateFragment(doc, doc.FirstChild, root, root);
                XmlNode featureRef = doc.FirstChild.AppendChild(doc.CreateElement("Feature", wixns));
                featureRef.Attributes.Append(doc.CreateAttribute("Id")).Value = MakeId(root.Name);
                featureRef.Attributes.Append(doc.CreateAttribute("Level")).Value = "1";
                featureRef.Attributes.Append(doc.CreateAttribute("Title")).Value = root.Name;
 foreach (String componentId in componentIds)
                {
                    XmlNode node = featureRef.AppendChild(doc.CreateElement("ComponentRef", wixns));
                    node.Attributes.Append(doc.CreateAttribute("Id")).Value = MakeId(componentId);
                }
 
 string formattedXml = null;
 using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    Encoding encodingWithNoByteOrderMark = new UTF8Encoding(false);
                    System.Xml.XmlTextWriter xmlWriter = new System.Xml.XmlTextWriter(ms, encodingWithNoByteOrderMark);
                    xmlWriter.Indentation = 4;
                    xmlWriter.Formatting = System.Xml.Formatting.Indented;
                    doc.WriteContentTo(xmlWriter);
                    xmlWriter.Close();
 
                    formattedXml = Encoding.UTF8.GetString(ms.ToArray());
                }
 
                Console.WriteLine(formattedXml);
 
 string outputFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "harvestingFiles.wxs");
                File.WriteAllText(outputFile, formattedXml);
                Console.WriteLine("Output >>>>>>>>>: " + outputFile);
 
                Console.ReadKey();
            }
 catch (Exception ex)
            {
                Console.WriteLine("ERROR: {0}", ex.Message);
            }
        }
    }
}

 

[出处:http://code.dblock.org/harvesting-wix-files]