#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
}
}