Click here to Skip to main content
15,891,943 members
Articles / Web Development / ASP.NET

A WIX web setup

Rate me:
Please Sign up or sign in to vote.
2.05/5 (8 votes)
9 May 20074 min read 71.9K   856   26  
Create WIX web setup using VS2005 and Wix 3.0
#region Using sourceDirrectives
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Reflection;
using System.Diagnostics;
using System.Configuration;
using System.Net;
using System.Security.AccessControl;
using System.Security.Principal;

#endregion

namespace Djans.ComponentWriter
{
    /// <summary>
    /// This class has the functionality to do the actual job of writing wix component file.
    /// </summary>
    class ComponentWriter
    {
        #region Private members
        static string sourceDirectory = string.Empty;
        static string componentFile = string.Empty;
        static string upgradeFile = string.Empty;
        static StringBuilder structure = new StringBuilder(string.Empty);
        static StringBuilder feature = new StringBuilder(string.Empty);
        #endregion

        /// <summary>
        /// Writes the wix files
        /// </summary>
        /// <param name="Config">Input values</param>
        /// <returns>Success or Failure</returns>
        public bool Write(ComponentWriterConfig Config)
        {
            // Set values
            sourceDirectory = Config.SourceDirectory;
            componentFile = Config.OutputFile;
            upgradeFile = Config.UgradeFile;

            // Start Writing: 
            // (i) Component.wxs 
            WriteComponents();

            // (ii) Update version number 
            if (!upgradeFile.Equals("-skip"))
                UpdateUpgradation();

            // Clear static variables
            ClearStaticVariables();

            return true;
        }

        #region Helper Functions

        /// <summary>
        /// Clears static variables after the writing is finished.        /// 
        /// </summary>
        private void ClearStaticVariables()
        {
            sourceDirectory = string.Empty;
            componentFile = string.Empty;
            upgradeFile = string.Empty;

            structure = new StringBuilder();
            feature = new StringBuilder();
        }

        /// <summary>
        /// Upgrades the version
        /// Updates only first 3 parts. The 4th part is always 0.
        /// </summary>
        /// <param name="version">Version number</param>
        private static void ChangeVersion(ref string version)
        {
            if (!String.IsNullOrEmpty(version))
            {
                string[] max = new string[4];
                max = version.Split('.');
                max[1] = ((Convert.ToInt32(max[1]) == 9) ? ("0") : (Convert.ToString(Convert.ToInt32(max[1]) + 1)));
                max[0] = ((Convert.ToInt32(max[1]) == 0) ? (Convert.ToString(Convert.ToInt32(max[0]) + 1)) : (max[0]));
                version = max[0] + "." + max[1] + "." + max[2] + ((max.Length > 3) ? ("." + max[3]) : (""));
            }
        }


        /// <summary>
        /// Provide New GUID
        /// </summary>
        /// <returns remarks="string">GUID</returns>
        private static string GetNewGUID()
        {
            return Guid.NewGuid().ToString().ToUpper();
        }
        #endregion

        #region WXS Generation

        /// <summary>
        /// Write component file
        /// </summary>
        private static void WriteComponents()
        {
            DirectoryInfo sourceDir = new DirectoryInfo(sourceDirectory);
            FileInfo[] sourceFiles = sourceDir.GetFiles("*.*");

            FileInfo componentFileInfo = new FileInfo(componentFile);
            if (componentFileInfo.Exists)
            {
                componentFileInfo.IsReadOnly = false;
            }

            StreamWriter w = new StreamWriter(componentFile, false);
            w.WriteLine(string.Format("<?xml version='1.0' encoding='utf-8'?>").Replace('\'', '"'));
            w.WriteLine(string.Format("<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>{0}<Fragment Id='ComponentFragment'>", Environment.NewLine).Replace('\'', '"'));
            w.WriteLine(string.Format("<Directory Id='TARGETDIR' Name='SourceDir'>").Replace('\'', '"'));
            w.WriteLine(string.Format("<Component Id='C__{0}' Guid='{1}' >", sourceDir.Name, Guid.NewGuid().ToString().ToUpper()).Replace('\'', '"'));

            feature.AppendLine(string.Format("<Feature Id='DefaultFeature' ConfigurableDirectory='TARGETDIR' Level='1'>").Replace('\'', '"'));
            feature.AppendLine(string.Format("<ComponentRef Id='C__{0}' />", sourceDir.Name).Replace('\'', '"'));

            foreach (FileInfo file in sourceFiles)
            {
                w.WriteLine(string.Format("<File Id='" + file.Name
                                          + "' Name='" + file.Name
                                          + "' Vital='yes' DiskId='1' Source='"
                                          + file.FullName
                                          + "' />").Replace('\'', '"'));
            }

            w.WriteLine("</Component>");
            GetDirectoryStructure(sourceDir);
            w.WriteLine(structure.ToString().Trim());
            w.WriteLine("</Directory>");

            // Add Feature            
            feature.AppendLine("</Feature>");
            w.WriteLine(feature.ToString().Trim());
            w.WriteLine("</Fragment></Wix>");

            // Close Writer
            w.Close();
        }

        /// <summary>
        /// Creates the directory structure based on the Source directory
        /// </summary>
        /// <param name="sourceDirectory">Source Directory</param>
        private static void GetDirectoryStructure(DirectoryInfo sourceDirectory)
        {
            StringBuilder subDirectoryStructure;
            DirectoryInfo[] subDirectories = sourceDirectory.GetDirectories("*", SearchOption.TopDirectoryOnly);
            foreach (DirectoryInfo subDir in subDirectories)
            {
                string id = string.Empty;
                if (structure.ToString().Contains(subDir.Name))
                    id = subDir.Parent.Name + "_" + subDir.Name;
                else
                    id = subDir.Name;

                subDirectoryStructure = new StringBuilder(string.Empty);
                subDirectoryStructure.AppendLine(string.Format("<Directory Id='DIR__{0}' Name='{1}'>", id, subDir.Name).Replace('\'', '"'));
                structure.Append(subDirectoryStructure.ToString());

                StringBuilder wixFileList;
                GetWixFormattedFilesList(subDir.GetFiles("*.*"), subDir, out wixFileList);
                if (wixFileList.Length > 0)
                    structure.Append(wixFileList.ToString().Trim());

                if (subDir.GetDirectories().Length > 0)
                {
                    GetDirectoryStructure(subDir);
                    structure.Append("</Directory>");
                }
                else
                {
                    structure.Append("</Directory>");
                }
            }
        }

        /// <summary>
        /// Lists the files in Wix Format
        /// </summary>
        /// <param name="files"></param>
        /// <param name="sourceDirectoryInfo"></param>
        /// <param name="wixFileList"></param>
        private static void GetWixFormattedFilesList(FileInfo[] files, DirectoryInfo sourceDirectoryInfo, out StringBuilder wixFileList)
        {
            wixFileList = new StringBuilder(string.Empty);
            StringBuilder wixCustomFile = new StringBuilder(string.Empty);
            if (files.Length > 0)
            {
                string id = string.Empty;
                string fileId = string.Empty;
                if (structure.ToString().Contains(sourceDirectoryInfo.Name))
                    id = sourceDirectoryInfo.Parent.Name + "_" + sourceDirectoryInfo.Name.Replace('-', '_');
                else
                    id = sourceDirectoryInfo.Name.Replace('-', '_');

                wixFileList.AppendLine(string.Format("<Component Id='C__{0}' Guid='{1}' >", id, Guid.NewGuid().ToString().ToUpper()).Replace('\'', '"'));
                feature.AppendLine(string.Format("<ComponentRef Id='C__{0}' />", id).Replace('\'', '"'));

                foreach (FileInfo file in files)
                {
                    if (structure.ToString().Contains(file.Name))
                        fileId = file.Directory.Name + "_" + file.Name.Replace('-', '_').Replace('.', '_');
                    else
                        fileId = file.Name.Replace('-', '_').Replace('.', '_');

                    //if (sourceDirr.Name == "bin")
                    if ((file.Name.Contains("Installer") || file.Name.Contains("Config_")) && (sourceDirectoryInfo.Name == "bin"))
                    {
                        feature.AppendLine(string.Format("<ComponentRef Id='C__{0}' />", file.Name.Replace('-', '_').Replace('.', '_')));
                        wixCustomFile.AppendLine(string.Format("<Component Id='C__{0}' Guid='{1}' >", file.Name.Replace('-', '_').Replace('.', '_').Replace('\'', '"'), Guid.NewGuid().ToString().ToUpper()).Replace('\'', '"'));
                        wixCustomFile.AppendLine(string.Format("<File Id='" + file.Name.Replace('-', '_').Replace('.', '_')
                                                  + "' Name='" + file.Name
                                                  + "' Vital='yes' DiskId='1"
                                                  + "' Source='" + file.FullName
                                                  + "' />").Replace('\'', '"'));
                        wixCustomFile.AppendLine("</Component>");                        
                    }
                    else
                    {
                        wixFileList.AppendLine(string.Format("<File Id='" + fileId.Replace('-', '_').Replace('#', '_').Replace('~', '_')
                                                  + "' Name='" + file.Name.Replace('-', '_').Replace('#', '_').Replace('~', '_')
                                                  + "' Vital='yes' DiskId='1"
                                                  + "' Source='" + file.FullName
                                                  + "' />").Replace('\'', '"'));
                    }

                }
                wixFileList.AppendLine("</Component>");
            }
            wixFileList.AppendLine(wixCustomFile.ToString());
        }

        /// <summary>
        /// Updates Version number in Upgrade code
        /// </summary>
        private static void UpdateUpgradation()
        {
            string newGuid = GetNewGUID();
            if (!String.IsNullOrEmpty(upgradeFile))
            {
                XmlDocument upgradeDoc = new XmlDocument();
                upgradeDoc.Load(upgradeFile);

                FileInfo file = new FileInfo(upgradeFile);
                if (file.Exists)
                    file.IsReadOnly = false;

                XmlNode node = upgradeDoc.SelectSingleNode("/*[local-name()='Wix' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi']/*[local-name()='Product' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi'][1]");
                node.Attributes["UpgradeCode"].Value = newGuid;
                node.Attributes["Id"].Value = GetNewGUID();
                string version = node.Attributes["Version"].Value;
                ChangeVersion(ref version);
                node.Attributes["Version"].Value = version;

                XmlNode upgradeChild = upgradeDoc.SelectSingleNode("/*[local-name()='Wix' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi']/*[local-name()='Product' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi'][1]/*[local-name()='Upgrade' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi'][1]");
                upgradeChild.Attributes["Id"].Value = newGuid;

                foreach (XmlNode child in upgradeChild.ChildNodes)
                {
                    if (child.LocalName.Equals("UpgradeVersion"))
                    {
                        string minVersion = string.Empty;
                        string maxVersion = string.Empty;
                        minVersion = child.Attributes["Minimum"].Value;
                        maxVersion = ((child.Attributes["Maximum"] == null) ? (string.Empty) : (child.Attributes["Maximum"].Value));
                        ChangeVersion(ref minVersion);
                        ChangeVersion(ref maxVersion);
                        child.Attributes["Minimum"].Value = minVersion;
                        if (child.Attributes["Maximum"] != null)
                            child.Attributes["Maximum"].Value = maxVersion;
                    }
                }

                upgradeDoc.SelectSingleNode("/*[local-name()='Wix' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi']/*[local-name()='Product' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi'][1]/*[local-name()='Upgrade' and namespace-uri()='http://schemas.microsoft.com/wix/2006/wi'][1]").InnerXml = upgradeChild.InnerXml;
                upgradeDoc.Save(upgradeFile);
            }
        }

        #endregion

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions