Beispiel #1
0
        /// <summary>
        /// Adds a feature record to the Features table.
        /// </summary>
        /// <param name="featureTable">The MSI database Feature table.</param>
        /// <param name="conditionTable">The MSI database Condition table.</param>
        /// <param name="ParentFeature">The name of this feature's parent.</param>
        /// <param name="database">The MSI database.</param>
        /// <param name="Feature">This Feature's Schema element.</param>
        /// <param name="Depth">The tree depth of this feature.</param>
        /// <param name="Order">The tree order of this feature.</param>
        private void AddFeature(InstallerTable featureTable, InstallerTable conditionTable, string ParentFeature,
                                InstallerDatabase database, MSIFeature Feature, int Depth, int Order)
        {
            const int TypicalInstallLevel    = 3;
            const int NonTypicalInstallLevel = 4;

            int featureInstallLevel = Feature.typical ? TypicalInstallLevel
                : NonTypicalInstallLevel;

            // Insert the Feature
            featureTable.InsertRecord(Feature.name, ParentFeature, Feature.title,
                                      Feature.description, Feature.display, featureInstallLevel,
                                      GetFeatureDirectory(Feature), Feature.attr);

            Log(Level.Verbose, "\t" + Feature.name);

            AddFeatureConditions(Feature, conditionTable);

            if (Feature.feature != null)
            {
                foreach (MSIFeature childFeature in Feature.feature)
                {
                    int newDepth = Depth + 1;
                    int newOrder = 1;

                    AddFeature(featureTable, conditionTable, Feature.name,
                               database, childFeature, newDepth, newOrder);
                    newOrder++;
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Loads the banner image.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadBannerImage(InstallerDatabase database)
        {
            // Try to open the Banner
            if (msi.banner != null)
            {
                string bannerFile = Path.Combine(Project.BaseDirectory, msi.banner);
                if (File.Exists(bannerFile))
                {
                    Log(Level.Verbose, "Storing banner '{0}'.", bannerFile);

                    using (InstallerRecordReader reader = database.FindRecords("Binary", new InstallerSearchClause("Name", Comparison.Equals, "bannrbmp"))) {
                        if (reader.Read())
                        {
                            // Write the Banner file to the MSI database
                            reader.SetValue(1, new InstallerStream(bannerFile));
                            reader.Commit();
                        }
                        else
                        {
                            throw new BuildException("Banner Binary record not found in template database.",
                                                     Location);
                        }
                    }
                }
                else
                {
                    throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                                                           "Unable to open banner image '{0}'.", bannerFile), Location);
                }
            }
        }
Beispiel #3
0
 /// <summary>
 /// Loads records for the Media table.
 /// </summary>
 /// <param name="database">The MSI database.</param>
 /// <param name="LastSequence">The sequence number of the last file in the .cab.</param>
 private void LoadMedia(InstallerDatabase database, int LastSequence)
 {
     // Open the "Media" Table
     using (InstallerTable mediaTable = database.OpenTable("Media")) {
         mediaTable.InsertRecord("1", LastSequence.ToString(), null,
                                 "#" + Path.GetFileNameWithoutExtension(msi.output) + ".cab", null, null);
     }
 }
 /// <summary>
 /// Loads records for the ModuleSignature table.
 /// </summary>
 /// <param name="database">The MSM database.</param>
 private void LoadModuleSignature(InstallerDatabase database) {
     if (msi.id != null) {
         Log(Level.Verbose, "Storing Module Signature:\n\tId:\t\t" + msi.id + "\n\tVersion:\t" + msi.version + "\n\tLanguage:\t" + Convert.ToInt32(msi.language));
         
         using (InstallerTable modsigTable = database.OpenTable("ModuleSignature")) {
             modsigTable.InsertRecord( msi.id, Convert.ToInt32(msi.language), msi.version );
         }
     }
 }
        /// <summary>
        /// Loads records for the ModuleInstallUISequence, ModuleInstallExecuteSequence,
        /// ModuleAdminUISequence, ModuleAdminExecute, and ModuleAdvtExecuteSequence tables.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleSequence(InstallerDatabase database)
        {
            // Add custom actions from Task definition
            if (msi.modulesequences != null)
            {
                Log(Level.Verbose, "Adding Module Install/Admin Sequences:");

                // Open the sequence tables
                using (InstallerTable
                       installExecuteTable = database.OpenTable("ModuleInstallExecuteSequence"),
                       installUITable = database.OpenTable("ModuleInstallUISequence"),
                       adminExecuteTable = database.OpenTable("ModuleAdminExecuteSequence"),
                       adminUITable = database.OpenTable("ModuleAdminUISequence"),
                       advtExecuteTable = database.OpenTable("ModuleAdvtExecuteSequence")) {
                    // Add binary data from Task definition
                    foreach (MSMModuleSequence sequence in msi.modulesequences)
                    {
                        Log(Level.Verbose, "\t" + sequence.action + " to the module" + sequence.type.ToString() + "sequence table.");

                        // Insert the record to the respective table

                        InstallerTable currentTable = null;

                        switch (sequence.type.ToString())
                        {
                        case "installexecute":
                            currentTable = installExecuteTable;
                            break;

                        case "installui":
                            currentTable = installUITable;
                            break;

                        case "adminexecute":
                            currentTable = adminExecuteTable;
                            break;

                        case "adminui":
                            currentTable = adminUITable;
                            break;

                        case "advtexecute":
                            currentTable = advtExecuteTable;
                            break;
                        }

                        if (currentTable != null)
                        {
                            currentTable.InsertRecord(sequence.action, Convert.ToInt32(sequence.sequence),
                                                      sequence.baseaction, Convert.ToInt32(sequence.after), sequence.condition);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the ModuleSignature table.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleSignature(InstallerDatabase database)
        {
            if (msi.id != null)
            {
                Log(Level.Verbose, "Storing Module Signature:\n\tId:\t\t" + msi.id + "\n\tVersion:\t" + msi.version + "\n\tLanguage:\t" + Convert.ToInt32(msi.language));

                using (InstallerTable modsigTable = database.OpenTable("ModuleSignature")) {
                    modsigTable.InsertRecord(msi.id, Convert.ToInt32(msi.language), msi.version);
                }
            }
        }
        /// <summary>
        /// Loads records for the ModuleConfiguration table.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleConfiguration(InstallerDatabase database)
        {
            if (msi.moduleconfigurations != null)
            {
                Log(Level.Verbose, "Adding Module Configurations:");

                using (InstallerTable modConfigurationTable = database.OpenTable("ModuleConfiguration")) {
                    // Add properties from Task definition
                    foreach (MSMModuleConfiguration configuration in msi.moduleconfigurations)
                    {
                        // Insert the Property

                        int format = 0;

                        switch (configuration.format.ToString())
                        {
                        case "text":
                            format = 0;
                            break;

                        case "key":
                            format = 1;
                            break;

                        case "integer":
                            format = 2;
                            break;

                        case "bitfield":
                            format = 3;
                            break;
                        }

                        if (configuration.name == null || configuration.name == "")
                        {
                            throw new BuildException("Configuration with no name attribute detected.",
                                                     Location);
                        }

                        modConfigurationTable.InsertRecord(configuration.name, format, configuration.type,
                                                           configuration.contextdata, configuration.defaultvalue, Convert.ToInt32(configuration.attr),
                                                           configuration.displayname, configuration.description, configuration.helplocation,
                                                           configuration.helpkeyword);

                        Log(Level.Verbose, "\t" + configuration.name);
                    }
                }
            }
        }
        protected override void LoadTypeSpecificDataFromTask(InstallerDatabase database, int lastSequence) {
            LoadModuleSignature(database);
            LoadModuleDependency(database);
            LoadModuleExclusion(database);
            LoadModuleSequence(database);
            LoadModuleIgnoreTable(database);
            LoadModuleSubstitution(database);
            LoadModuleConfiguration(database);

            // Commit the MSI Database
            database.Commit();

            ReorderFiles(database, ref lastSequence);

            // Delete unused tables
            Log(Level.Verbose, "Dropping unused tables");
            database.DropEmptyTables(true);
        }
        protected override void LoadTypeSpecificDataFromTask(InstallerDatabase database, int lastSequence) {
            LoadLaunchCondition(database);
            LoadFeatures(database);

            // The database file must be closed for merging to succeed
            database.Close();

            LoadMergeModules(database.ArchivePath, TempFolderPath);

            // Reopen database after merging
            database.Open();

            ReorderFiles(database, ref lastSequence);
            LoadMedia(database, lastSequence);
            LoadBannerImage(database);
            LoadBackgroundImage(database);
            LoadLicense(database);
        }
Beispiel #10
0
        /// <summary>
        /// Loads the license file.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadLicense(InstallerDatabase database)
        {
            if (msi.license != null)
            {
                // Find the License control
                using (InstallerRecordReader recordReader = database.FindRecords("Control", new InstallerSearchClause("Control", Comparison.Equals, "AgreementText"))) {
                    if (recordReader.Read())
                    {
                        string licFile = Path.Combine(Project.BaseDirectory, msi.license);
                        Log(Level.Verbose, "Storing license '{0}'.", licFile);

                        // make sure license exists
                        if (!File.Exists(licFile))
                        {
                            throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                                                                   "License file '{0}' does not exist.", licFile),
                                                     Location);
                        }

                        StreamReader licenseFileReader = null;
                        try {
                            licenseFileReader = File.OpenText(licFile);
                        } catch (IOException ex) {
                            throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                                                                   "Unable to open license file '{0}'.", licFile),
                                                     Location, ex);
                        }

                        try {
                            recordReader.SetValue(9, licenseFileReader.ReadToEnd());
                            recordReader.Commit();
                        } finally {
                            licenseFileReader.Close();
                        }
                    }
                    else
                    {
                        throw new BuildException("Couldn't find AgreementText Control in template database.",
                                                 Location);
                    }
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Loads records for the LaunchCondition table
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadLaunchCondition(InstallerDatabase database)
        {
            // Add properties from Task definition
            if (msi.launchconditions != null)
            {
                Log(Level.Verbose, "Adding Launch Conditions:");

                // Open the Launch Condition Table
                using (InstallerTable table = database.OpenTable("LaunchCondition")) {
                    // Add binary data from Task definition
                    foreach (MSILaunchCondition launchCondition in msi.launchconditions)
                    {
                        Log(Level.Verbose, "\t" + launchCondition.name);

                        table.InsertRecord(launchCondition.condition, launchCondition.description);
                    }
                }
            }
        }
        protected override void LoadTypeSpecificDataFromTask(InstallerDatabase database, int lastSequence)
        {
            LoadModuleSignature(database);
            LoadModuleDependency(database);
            LoadModuleExclusion(database);
            LoadModuleSequence(database);
            LoadModuleIgnoreTable(database);
            LoadModuleSubstitution(database);
            LoadModuleConfiguration(database);

            // Commit the MSI Database
            database.Commit();

            ReorderFiles(database, ref lastSequence);

            // Delete unused tables
            Log(Level.Verbose, "Dropping unused tables");
            database.DropEmptyTables(true);
        }
Beispiel #13
0
        protected override void LoadTypeSpecificDataFromTask(InstallerDatabase database, int lastSequence)
        {
            LoadLaunchCondition(database);
            LoadFeatures(database);

            // The database file must be closed for merging to succeed
            database.Close();

            LoadMergeModules(database.ArchivePath, TempFolderPath);

            // Reopen database after merging
            database.Open();

            ReorderFiles(database, ref lastSequence);
            LoadMedia(database, lastSequence);
            LoadBannerImage(database);
            LoadBackgroundImage(database);
            LoadLicense(database);
        }
Beispiel #14
0
        /// <summary>
        /// Loads records for the Features table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadFeatures(InstallerDatabase database)
        {
            if (msi.features == null)
            {
                return;
            }

            Log(Level.Verbose, "Adding Features:");

            using (InstallerTable featureTable = database.OpenTable("Feature"), conditionTable = database.OpenTable("Condition")) {
                // Add features from Task definition
                int order = 1;
                int depth = 1;

                foreach (MSIFeature feature in msi.features)
                {
                    AddFeature(featureTable, conditionTable, null, database, feature, depth, order);
                    order++;
                }
            }
        }
        /// <summary>
        /// Loads records for the ModuleSubstitution table.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleSubstitution(InstallerDatabase database)
        {
            if (msi.modulesubstitutions != null)
            {
                Log(Level.Verbose, "Adding Module Substitutions:");

                using (InstallerTable modSubstitutionTable = database.OpenTable("ModuleSubstitution")) {
                    foreach (MSMModuleSubstitution substitution in msi.modulesubstitutions)
                    {
                        if (substitution.table == null || substitution.table == "")
                        {
                            throw new BuildException("Substitution with no table attribute detected.",
                                                     Location);
                        }

                        modSubstitutionTable.InsertRecord(substitution.table, substitution.row, substitution.column, substitution.value);

                        Log(Level.Verbose, "\tRow: " + substitution.row + "\tColumn: " + substitution.column);
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the ModuleIgnoreTable table.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleIgnoreTable(InstallerDatabase database)
        {
            if (msi.moduleignoretables != null)
            {
                Log(Level.Verbose, "Adding Tables To Ignore:");

                using (InstallerTable modIgnoreTableTable = database.OpenTable("ModuleIgnoreTable")) {
                    foreach (MSMModuleIgnoreTable table in msi.moduleignoretables)
                    {
                        if (table.name == null || table.name == "")
                        {
                            throw new BuildException("Table with no name attribute detected.",
                                                     Location);
                        }

                        modIgnoreTableTable.InsertRecord(table.name);

                        Log(Level.Verbose, "\t" + table.name);
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the ModuleDependency table.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleDependency(InstallerDatabase database)
        {
            if (msi.moduledependencies != null)
            {
                Log(Level.Verbose, "Adding Module Dependencies:");

                using (InstallerTable modDepTable = database.OpenTable("ModuleDependency")) {
                    foreach (MSMModuleDependency dependency in msi.moduledependencies)
                    {
                        if (dependency.id == null || dependency.id == "")
                        {
                            throw new BuildException("Dependency with no id attribute detected.",
                                                     Location);
                        }

                        modDepTable.InsertRecord(msi.id, Convert.ToInt32(msi.language), dependency.id,
                                                 Convert.ToInt32(dependency.language), dependency.version);

                        Log(Level.Verbose, " - " + dependency.id);
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the ModuleExclusion table.
        /// </summary>
        /// <param name="database">The MSM database.</param>
        private void LoadModuleExclusion(InstallerDatabase database)
        {
            if (msi.moduleexclusions != null)
            {
                Log(Level.Verbose, "Adding Module Exclusions:");

                using (InstallerTable modExTable = database.OpenTable("ModuleExclusion")) {
                    foreach (MSMModuleExclusion exclusion in msi.moduleexclusions)
                    {
                        // Insert the Property
                        if (exclusion.id == null || exclusion.id == "")
                        {
                            throw new BuildException("Exclusion with no id attribute detected.",
                                                     Location);
                        }

                        modExTable.InsertRecord(msi.id, Convert.ToInt32(msi.language), exclusion.id,
                                                Convert.ToInt32(exclusion.language), exclusion.minversion, exclusion.maxversion);

                        Log(Level.Verbose, " - " + exclusion.id);
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the _UrlToDir table.
        /// "Load the url properties to convert
        /// url properties to a properties object" ??
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadUrlProperties(InstallerDatabase database) {
            if (msi.urlproperties == null)
                return;

            Log(Level.Verbose, "Adding URL Properties:");

            using (InstallerTable urlpropTable = database.OpenTable("_UrlToDir")) {
                foreach (MSIURLProperty urlprop in msi.urlproperties) {
                    Log(Level.Verbose, "\t" + urlprop.name);

                    urlpropTable.InsertRecord(urlprop.name, urlprop.property);
                }
            }
        }
        /// <summary>
        /// Loads records for the _AppMappings table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadAppMappings(InstallerDatabase database) {
            if (msi.appmappings == null)
                return;

            Log(Level.Verbose, "Adding Application Mappings:");

            using (InstallerTable appmapTable = database.OpenTable("_AppMappings")) {
                foreach (MSIAppMapping appmap in msi.appmappings) {
                    Log(Level.Verbose, "\t" + appmap.directory);

                    appmapTable.InsertRecord(appmap.directory, appmap.extension, appmap.exepath, appmap.verbs);
                }
            }
        }
        /// <summary>
        /// Loads records for the ActionText table.  Allows users to specify descriptions/templates for actions.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadActionText(InstallerDatabase database) {
            if (msi.actiontext == null)
                return;

            Log(Level.Verbose, "Adding ActionText:");

            using (InstallerTable actionTextTable = database.OpenTable("ActionText")) {
                foreach (MSIActionTextAction action in msi.actiontext) {
                    Log(Level.Verbose, "\t" + action.name);

                    try {
                        actionTextTable.InsertRecord(action.name, action.description, action.template);
                    } catch (Exception) {
                        Log(Level.Warning, "Action text for '{0}' already"
                            + " exists in the database.", action.name);
                    }
                }
            }
        }
        /// <summary>
        /// Adds a file record to the Files table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="directoryTable">The MSI database view.</param>
        /// <param name="Component">The Component's XML Element.</param>
        /// <param name="fileTable">The MSI database view.</param>
        /// <param name="ComponentDirectory">The directory of this file's component.</param>
        /// <param name="ComponentName">The name of this file's component.</param>
        /// <param name="Sequence">The installation sequence number of this file.</param>
        /// <param name="msiAssemblyTable">View containing the MsiAssembly table.</param>
        /// <param name="msiAssemblyNameTable">View containing the MsiAssemblyName table.</param>
        /// <param name="componentTable">View containing the Components table.</param>
        /// <param name="featureComponentTable">View containing the FeatureComponents table.</param>
        /// <param name="classTable">View containing the Class table.</param>
        /// <param name="progIdTable">View containing the ProgId table.</param>
        /// <param name="selfRegTable">View containing the SelfReg table.</param>
        /// <param name="modComponentTable">ModuleComponent table.</param>
        private void AddFiles(InstallerDatabase database, InstallerTable directoryTable, MSIComponent Component,
            InstallerTable fileTable, string ComponentDirectory, string ComponentName, 
            ref int Sequence, InstallerTable msiAssemblyTable, InstallerTable msiAssemblyNameTable,
            InstallerTable componentTable, InstallerTable featureComponentTable, InstallerTable classTable, InstallerTable progIdTable,
            InstallerTable selfRegTable, InstallerTable modComponentTable) {

            XmlElement fileSetElem = (XmlElement)((XmlElement)_xmlNode).SelectSingleNode(
                "nant:components/nant:component[@id='" + Component.id + "']/nant:fileset", NamespaceManager);

            FileSet componentFiles = (FileSet) Element.InitializeBuildElement(
                task, fileSetElem, new FileSet(), typeof(FileSet));

            /*
            if (componentFiles.BaseDirectory == null) {
                componentFiles.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
            }
            */

            string basePath = componentFiles.BaseDirectory.FullName;
            Hashtable dirMap = new Hashtable();
            Hashtable componentMap = new Hashtable();

            foreach (string filePath in componentFiles.FileNames) {
                // Insert the File
                string fileName = Path.GetFileName(filePath);
                string dirPath = Path.GetDirectoryName(filePath);

#region Build the subdirectory structure -- Component.keepsubdirs == true
                if (Component.keepsubdirs) {
                    // foreach file, add intermediate directory records as needed
                    //    foreach directory record added that has at least one file
                    //       add a component record
                    //       hook the component record up to the feature
                    // add the file
                    string tmpDirPath = dirPath;

                    // Add intermediate directory records to the directory table
                    // List of sub directory names.  
                    ArrayList subdirList = new ArrayList();
                    if (basePath.EndsWith(Path.DirectorySeparatorChar.ToString()) || basePath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
                        basePath = basePath.Substring(0, basePath.Length - 1);

                    while (tmpDirPath != basePath) {
                        subdirList.Insert(0, Path.GetFileName(tmpDirPath));
                        tmpDirPath = Path.GetDirectoryName(tmpDirPath);
                    }

                    tmpDirPath = basePath;
                    string parentDir = Component.directory;
                    string relativeDirId = Component.directory;
                    foreach (string folderName in subdirList) {
                        tmpDirPath = Path.Combine(tmpDirPath, folderName);
                        relativeDirId += "_" + folderName.ToUpper();

                        // Directory column is an identifier: identifiers may
                        // contain the ASCII characters A-Z (a-z), digits, 
                        // underscores (_), or periods (.). However, every
                        // identifier must begin with either a letter or an 
                        // underscore.

                        relativeDirId = relativeDirId.Replace(" ","_");

                        if (!dirMap.ContainsKey(tmpDirPath)) {
                            // Add entry to directory table
                            dirMap[tmpDirPath] = relativeDirId;

                            string path = GetShortPath(tmpDirPath) + "|" + folderName;
                        
                            // Insert the directory record
                            directoryTable.InsertRecord(relativeDirId, parentDir, path);
                            parentDir = relativeDirId;
                        } else {
                            parentDir = (string)dirMap[tmpDirPath];
                        }
                    }

                    tmpDirPath = dirPath;

                    if (tmpDirPath != basePath && !componentMap.ContainsKey(tmpDirPath)) {
                        // Create a component for this path.

                        string name = "C_" + CreateIdentityGuid();
                        componentMap[tmpDirPath] = name;
                        string newCompId = CreateRegistryGuid();
                        string directoryRef = (string)dirMap[tmpDirPath];

                        // Add a record for a new Component
                        componentTable.InsertRecord(name, newCompId, directoryRef, Component.attr, Component.condition, null);

                        // The null GUID is authored into any field of a msm database that references a feature.  It gets replaced
                        // with the guid of the feature assigned to the merge module.
                        string feature = "{00000000-0000-0000-0000-000000000000}";
                        if (featureComponents[ComponentName] != null) {
                            feature = (string)featureComponents[ComponentName];
                        }

                        // Map the new Component to the existing one's Feature (FeatureComponents is only used in MSI databases)
                        featureComponentTable.InsertRecord(feature, name);                        
                    }
                }
#endregion

                MSIFileOverride fileOverride = null;

                if (Component.forceid != null) {
                    foreach (MSIFileOverride curOverride in Component.forceid) {
                        if (curOverride.file == fileName) {
                            fileOverride = curOverride;
                            break;
                        }
                    }
                }

                string fileId = fileOverride == null ?
                    CreateIdentityGuid() :
                    fileOverride.id;

                // If the user specifies forceid & specified a file attribute, use it.  Otherwise use the
                // fileattr assigned to the component.
                int fileAttr = ((fileOverride == null) || (fileOverride.attr == 0)) ? Component.fileattr : fileOverride.attr;

                if (Component.keepsubdirs && dirMap.ContainsKey(dirPath)) {
                    // The file is down a subdirectory path
                    string dirValue = (string)dirMap[dirPath];
                    files.Add(dirValue + "|" + fileName, fileId);
                } else {
                    // Used to determine the keyfile
                    files.Add(Component.directory + "|" + fileName, fileId);
                }

                string fileSize;

                try {
                    fileSize = new FileInfo(filePath).Length.ToString();
                } catch (Exception ex) {
                    throw new BuildException(String.Format(CultureInfo.InvariantCulture, "Could not open file {0}", filePath), Location, ex);
                }

                Log(Level.Verbose, "\t" + filePath);

                // If the file is an assembly, create a new component to contain it,
                // add the new component, map the new component to the old component's
                // feature, and create an entry in the MsiAssembly and MsiAssemblyName
                // table.
                //
                bool isAssembly = false;
                Assembly fileAssembly = null;
                string fileVersion = string.Empty;
                try {
                    FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(filePath);
                    fileVersion = string.Format(CultureInfo.InvariantCulture, 
                        "{0}.{1}.{2}.{3}", fileVersionInfo.FileMajorPart, 
                        fileVersionInfo.FileMinorPart, fileVersionInfo.FileBuildPart, 
                        fileVersionInfo.FilePrivatePart);
                } catch {}

                try {
                    fileAssembly = Assembly.LoadFrom(filePath);
                    fileVersion = fileAssembly.GetName().Version.ToString();
                    isAssembly = true;
                } catch {}

                // Set the file version equal to the override value, if present
                if ((fileOverride != null) && (fileOverride.version != null) && (fileOverride.version != string.Empty)) {
                    fileVersion = fileOverride.version;
                }

                if (!IsVersion(ref fileVersion)) {
                    fileVersion = null;
                }

                string componentFieldValue = Component.name;

                if (isAssembly || filePath.EndsWith(".tlb")) {
                    // The null GUID is authored into any field of a msm database that references a feature.  It gets replaced
                    // with the guid of the feature assigned to the merge module.
                    string feature = "{00000000-0000-0000-0000-000000000000}";
                    if (featureComponents[ComponentName] != null)
                        feature = (string)featureComponents[ComponentName];

                    string asmCompName = ComponentName;

                    if ((componentFiles.FileNames.Count > 1) && !fileName.ToLower().Equals(Component.key.file.ToLower())) {
                        asmCompName = "C_" + fileId;
                        componentFieldValue = asmCompName;
                        string newCompId = CreateRegistryGuid();

                        // Add a record for a new Component
                        componentTable.InsertRecord(asmCompName, newCompId, ComponentDirectory, Component.attr, Component.condition, fileId);

                        if (modComponentTable != null) {
                            AddModuleComponentVirtual(database, modComponentTable, asmCompName);
                        }
                        else {
                            // Map the new Component to the existing one's Feature (FeatureComponents is only used in MSI databases)
                            featureComponentTable.InsertRecord(feature, asmCompName);                        
                        }
                    }

                    if (isAssembly) {
                        bool installToGAC = ((fileOverride == null) || (fileOverride.installtogac == false)) ? Component.installassembliestogac : fileOverride.installtogac;
                        // Add a record for a new MsiAssembly
                        if (installToGAC) {
                            msiAssemblyTable.InsertRecord(asmCompName, feature, fileId, null, 0);
                        }
                        else {
                            msiAssemblyTable.InsertRecord(asmCompName, feature, fileId, fileId, 0);
                        }

                        AddAssemblyManifestRecords(fileAssembly, msiAssemblyNameTable, asmCompName);

                        bool checkInterop = Component.checkinterop;

                        if (fileOverride != null) {
                            checkInterop = fileOverride.checkinterop;
                        }

                        if (checkInterop) {
                            CheckAssemblyForCOMInterop(
                                database, filePath, fileAssembly, ComponentName,
                                asmCompName, classTable, progIdTable);
                        }

                        // File can't be a member of both components
//                        if (componentFiles.FileNames.Count > 1) {
//                            files.Remove(ComponentDirectory + "|" + fileName);
//                            files.Add(ComponentDirectory + "|" + fileName, "KeyIsDotNetAssembly");
//                        }
                    } else if (filePath.EndsWith(".tlb")) {
                        typeLibComponents.Add(
                            Path.GetFileName(filePath),
                            asmCompName);
                    }
                }

                if (filePath.EndsWith(".dll") || filePath.EndsWith(".ocx")) {
                    int hmod = LoadLibrary(filePath);
                    if (hmod != 0) {
                        int regSvr = GetProcAddress(hmod, "DllRegisterServer");
                        if (regSvr != 0) {
                            Log(Level.Info, "Configuring '{0}' for COM Self Registration...",
                                Path.GetFileName(filePath));

                            // Add a record for a new Component
                            selfRegTable.InsertRecord(fileId, null);
                        }
                        FreeLibrary(hmod);
                    }

                    // Register COM .dlls with an embedded
                    // type library for self registration.
                }

                CopyToTempFolder(filePath, fileId);

//                if (!isAssembly && !filePath.EndsWith(".tlb")
//                    || componentFiles.FileNames.Count == 1) {
//                    componentFieldValue = Component.name;
//                }

                // propagate language (if available) to File table to avoid 
                // ICE60 verification warnings
                string language = GetLanguage(isAssembly, fileAssembly, filePath);

                Sequence++;

                if (Component.keepsubdirs && componentMap.ContainsKey(dirPath)) {
                    // Use the component for the file's path
                    componentFieldValue = (string)componentMap[dirPath];
                }

                fileTable.InsertRecord(fileId, componentFieldValue, GetShortFile(filePath) + "|" + fileName, 
                    fileSize, fileVersion, language, fileAttr, Sequence.ToString());
            }
        }
Beispiel #23
0
 protected override void AddModuleComponentVirtual(InstallerDatabase database, InstallerTable modComponentTable, string componentName)
 {
 }
        /// <summary>
        /// Creates a .cab file with all source files included.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void CreateCabFile(InstallerDatabase database) {
            Log(Level.Info, "Compressing Files...");

            string shortCabDir = GetShortDir(Path.Combine(Project.BaseDirectory, msi.sourcedir));
            string cabFilePath = shortCabDir + @"\" + CabFileName;

            if (!Directory.Exists(TempFolderPath))
                Directory.CreateDirectory(TempFolderPath);

            // holds output buffer
            MemoryStream ms = new MemoryStream();

            // create task for creating cab file
            ExecTask cabarcTask = new ExecTask();
            cabarcTask.Project = Project;
            cabarcTask.Parent = task;
            cabarcTask.Verbose = Verbose;
            // write output to (Memory)Stream
            cabarcTask.ErrorWriter = cabarcTask.OutputWriter = new StreamWriter(ms);
            // set tool to execute
            cabarcTask.FileName = "cabarc";
            // set command line arguments
            cabarcTask.CommandLineArguments = "-r N " + cabFilePath + " *";
            // use directory containing files to add as working directory
            cabarcTask.WorkingDirectory = new DirectoryInfo(TempFolderPath);

            try {
                // increment indentation level
                cabarcTask.Project.Indent();

                // execute task
                cabarcTask.Execute();
            } catch (Exception ex) {
                // read output of cabarc
                ms.Position = 0;
                StreamReader sr = new StreamReader(ms);
                string output = sr.ReadToEnd();
                sr.Close();

                // if anything was output, log it as warning
                if (output.Length != 0) {
                    cabarcTask.Log(Level.Warning, output);
                }
                
                string path = Environment.GetEnvironmentVariable ("PATH");
                if (path != null) {
                    Console.WriteLine ("PATH=" + path);
                    PathScanner scanner = new PathScanner ();
                    scanner.Add ("cabarc.exe");
                    StringCollection files = scanner.Scan ();
                    if (files.Count > 0) {
                        foreach (string file in files)
                            Console.WriteLine ("FILE=" + file);
                    } else {
                            Console.WriteLine ("NOT FOUND IN PATH!");
                    }
                }

                // signal error
                throw new BuildException("Error creating cab file.", Location, ex);
            } finally {
                // restore indentation level
                cabarcTask.Project.Unindent();

                // close MemoryStream
                ms.Close();
            }

            if (File.Exists(cabFilePath)) {
                Log(Level.Verbose, "Storing Cabinet in Installer Database...");

                using (InstallerTable cabTable = database.OpenTable("_Streams")) {
                    cabTable.InsertRecord(Path.GetFileName(cabFilePath), 
                        new InstallerStream(cabFilePath));
                }
            } else {
                throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                    "Cabinet file '{0}' does not exist.", cabFilePath), Location);
            }
        }
        /// <summary>
        /// Loads properties for the Summary Information Stream.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadSummaryInformation(InstallerDatabase database) {
            string title = string.Empty;
            string subject = string.Empty;
            string author = string.Empty;
            string keywords = string.Empty;
            string comments = string.Empty; 
            string template = string.Empty;
            string revisionNumber = CreateRegistryGuid();
            string creatingApplication = "NAnt";

            // First try to get the values from the specified properties
            if (msi.properties != null) {
                foreach (property prop in msi.properties) {
                    if (prop.name == "ProductName") {
                        title = subject = prop.value;
                    } else if (prop.name == "Manufacturer") {
                        author = prop.value;
                    } else if (prop.name == "Keywords") {
                        keywords = prop.value;
                    } else if (prop.name == "Comments") {
                        comments = prop.value;
                    }
                }
            }

            // Now attempt to get the values from the <summaryinformation> element
            if (msi.summaryinformation != null) {
                if (msi.summaryinformation.title != null) {
                    title = msi.summaryinformation.title;
                }
                if (msi.summaryinformation.subject != null) {
                    subject = msi.summaryinformation.subject;
                }
                if (msi.summaryinformation.author != null) {
                    author = msi.summaryinformation.author;
                }
                if (msi.summaryinformation.keywords != null) {
                    keywords = msi.summaryinformation.keywords;
                }
                if (msi.summaryinformation.comments != null) {
                    comments = msi.summaryinformation.comments;
                }
                if (msi.summaryinformation.template != null) {
                    template = msi.summaryinformation.template;
                }
                if (msi.summaryinformation.revisionnumber != null) {
                    revisionNumber = msi.summaryinformation.revisionnumber;
                }
                if (msi.summaryinformation.creatingapplication != null) {
                    creatingApplication = msi.summaryinformation.creatingapplication;
                }
            }

            SummaryInfo summaryInfo = database.GetSummaryInformation();
            if (!String.IsNullOrEmpty(title)) {
                summaryInfo.set_Property(2, title);
            }
            if (!String.IsNullOrEmpty(subject)) {
                summaryInfo.set_Property(3, subject);
            }
            if (!String.IsNullOrEmpty(author)) {
                summaryInfo.set_Property(4, author);
            }
            if (!String.IsNullOrEmpty(keywords)) {
                summaryInfo.set_Property(5, keywords);
            }
            if (!String.IsNullOrEmpty(comments)) {
                summaryInfo.set_Property(6, comments);
            }
            if (!String.IsNullOrEmpty(template)) {
                summaryInfo.set_Property(7, template);
            }

            summaryInfo.set_Property(9, revisionNumber);

            summaryInfo.set_Property(14, 200);
            summaryInfo.set_Property(15, 2);

            if (!String.IsNullOrEmpty(creatingApplication)) {
                summaryInfo.set_Property(18, creatingApplication);
            }

            summaryInfo.Persist();
        }
        /// <summary>
        /// Loads records for the _IISProperties table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadIISDirectoryProperties(InstallerDatabase database) {
            if (msi.iisproperties == null)
                return;

            Log(Level.Verbose, "Adding IIS Directory Properties:");

            using (InstallerTable iispropTable = database.OpenTable("_IISProperties")) {
                foreach (MSIIISProperty iisprop in msi.iisproperties) {
                    Log(Level.Verbose, "\t" + iisprop.directory);

                    iispropTable.InsertRecord(iisprop.directory, iisprop.attr, iisprop.defaultdoc);
                }
            }
        }
        /// <summary>
        /// Loads records for the _VDirToUrl table.
        /// Used for converting a vdir to an url
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadVDirProperties(InstallerDatabase database) {
            if (msi.vdirproperties == null)
                return;

            Log(Level.Verbose, "Adding VDir Properties:");

            using (InstallerTable vdirpropTable = database.OpenTable("_VDirToUrl")) {
                foreach (MSIVDirProperty vdirprop in msi.vdirproperties) {
                    Log(Level.Verbose, "\t" + vdirprop.name);

                    vdirpropTable.InsertRecord(vdirprop.name, vdirprop.portproperty, vdirprop.urlproperty);
                }
            }
        }
 protected override void AddModuleComponentVirtual(InstallerDatabase database, InstallerTable modComponentTable, string componentName)
 {
     // Add the new component to the modulecomponents table
     modComponentTable.InsertRecord(componentName, msi.id, Convert.ToInt32(msi.language));
 }
        /// <summary>
        /// Loads records for the _AppRootCreate table.
        /// Used for making a virtual directory a virtual application
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadAppRootCreate(InstallerDatabase database) {
            if (msi.approots == null)
                return;

            Log(Level.Verbose, "Adding Application Roots:");

            using (InstallerTable approotTable = database.OpenTable("_AppRootCreate")) {
                foreach (MSIAppRoot appRoot in msi.approots) {
                    Log(Level.Verbose, "\t" + appRoot.urlproperty);

                    approotTable.InsertRecord(appRoot.component, appRoot.urlproperty, appRoot.inprocflag);
                }
            }
        }
        /// <summary>
        /// Loads records for the Properties table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadProperties(InstallerDatabase database) {
            if (msi.properties == null)
                return;

            using (InstallerTable propertyTable = database.OpenTable("Property")) {
                Log(Level.Verbose, "Adding Properties:");

                property productName = null;
                property productCode = null;
                property productVersion = null;
                property manufacturer = null;

                // Add properties from Task definition
                foreach (property property in msi.properties) {
                    // Insert the Property
                    string name = property.name;
                    string sValue = property.value;

                    if (name == "ProductName") {
                        productName = property;
                    } else if (name == "ProductCode") {
                        productCode = property;
                    } else if (name == "ProductVersion") {
                        productVersion = property;
                    } else if (name == "Manufacturer") {
                        manufacturer = property;
                    }

                    if (name == null || name.Length == 0) {
                        throw new BuildException("Property with no name attribute detected.", Location);
                    }

                    if (sValue == null || sValue.Length == 0) {
                        throw new BuildException(String.Format(CultureInfo.InvariantCulture, "Property {0} has no value.", name), Location);
                    }

                    propertyTable.InsertRecord(name, sValue);

                    Log(Level.Verbose, "\t" + name);
                }

                if ((productName == null) && (this is MsiCreationCommand))
                    throw new BuildException("ProductName property must be specified.  For more information please visit: http://msdn.microsoft.com/library/en-us/msi/setup/productname_property.asp");
                if ((productCode == null) && (this is MsiCreationCommand))
                    throw new BuildException("ProductCode property must be specified.  For more information please visit: http://msdn.microsoft.com/library/en-us/msi/setup/productcode_property.asp");
                if ((productVersion == null) && (this is MsiCreationCommand))
                    throw new BuildException("ProductVersion property must be specified.  For more information please visit: http://msdn.microsoft.com/library/en-us/msi/setup/productversion_property.asp");
                if ((manufacturer == null) && (this is MsiCreationCommand))
                    throw new BuildException("Manufacturer property must be specified.  For more information please visit: http://msdn.microsoft.com/library/en-us/msi/setup/manufacturer_property.asp");
            }        
        }
        /// <summary>
        /// Enumerates the registry to see if an assembly has been registered
        /// for COM interop, and if so adds these registry keys to the Registry
        /// table, ProgIds to the ProgId table, classes to the Classes table,
        /// and a TypeLib to the TypeLib table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="fileName">The Assembly filename.</param>
        /// <param name="fileAssembly">The Assembly to check.</param>
        /// <param name="componentName">The name of the containing component.</param>
        /// <param name="assemblyComponentName">The name of the containing component's assembly GUID.</param>
        /// <param name="classTable">View containing the Class table.</param>
        /// <param name="progIdTable">View containing the ProgId table.</param>
        private void CheckAssemblyForCOMInterop(InstallerDatabase database, string fileName, Assembly fileAssembly,
            string componentName, string assemblyComponentName, InstallerTable classTable, InstallerTable progIdTable) {
            AssemblyName asmName = fileAssembly.GetName();
            string featureName = (string)featureComponents[componentName];
            string typeLibName = Path.GetFileNameWithoutExtension(fileName) + ".tlb";
            string typeLibFileName = Path.Combine(Path.GetDirectoryName(fileName), typeLibName);

            bool foundTypeLib = false;

            // Register the TypeLibrary
            RegistryKey typeLibsKey = Registry.ClassesRoot.OpenSubKey("Typelib", false);

            string[] typeLibs = typeLibsKey.GetSubKeyNames();
            foreach (string typeLib in typeLibs) {
                RegistryKey typeLibKey = typeLibsKey.OpenSubKey(typeLib, false);
                if (typeLibKey == null)
                    continue;
                string[] typeLibSubKeys = typeLibKey.GetSubKeyNames();
                foreach (string typeLibSubKey in typeLibSubKeys) {
                    RegistryKey win32Key = typeLibKey.OpenSubKey(typeLibSubKey + @"\0\win32");
                    if (win32Key == null)
                        continue;
                    string curTypeLibFileName = (string)win32Key.GetValue(null, null);
                    if (curTypeLibFileName != null) {
                        if (String.Compare(curTypeLibFileName, typeLibFileName, true) == 0) {
                            Log(Level.Info, "Configuring '{0}' for COM Interop...", 
                                typeLibName);

                            TypeLibRecord tlbRecord = new TypeLibRecord(
                                typeLib, typeLibFileName,
                                asmName, featureName, assemblyComponentName);

                            typeLibRecords.Add(tlbRecord);

                            foundTypeLib = true;
                            win32Key.Close();
                            break;
                        }
                    }
                    win32Key.Close();
                }
                typeLibKey.Close();

                if (foundTypeLib)
                        break;
            }
            typeLibsKey.Close();

            // Register CLSID(s)
            RegistryKey clsidsKey = Registry.ClassesRoot.OpenSubKey("CLSID", false);

            string[] clsids = clsidsKey.GetSubKeyNames();
            foreach (string clsid in clsids) {
                RegistryKey clsidKey = clsidsKey.OpenSubKey(clsid, false);
                if (clsidKey == null)
                    continue;

                RegistryKey inprocKey = clsidKey.OpenSubKey("InprocServer32", false);
                if (inprocKey == null) {
                    clsidKey.Close();
                    continue;
                }

                string clsidAsmName = (string)inprocKey.GetValue("Assembly", null);
                if (clsidAsmName != null) {
                    if (asmName.FullName == clsidAsmName) {
                        // Register ProgId(s)
                        RegistryKey progIdKey = clsidKey.OpenSubKey("ProgId", false);
                        if (progIdKey != null) {
                            string progId = (string)progIdKey.GetValue(null, null);
                            string className = (string)clsidKey.GetValue(null, null);

                            if (progId != null) {
                                progIdTable.InsertRecord(progId, null, clsid, className, null, 0);
                                classTable.InsertRecord(clsid, "InprocServer32", assemblyComponentName, progId, className, null, null, null, 0, null, null, featureName, 0);
                            }
                            progIdKey.Close();
                            progIdKey = null;
                        }
                    }
                }
                inprocKey.Close();
                clsidKey.Close();
            }
            clsidsKey.Close();
        }
 private void LoadCommonDataFromTask(InstallerDatabase database, ref int fileSequenceNumber) {
     LoadProperties(database);
     // Remove this next line
     LoadDepreciatedLocators(database);
     LoadRegistryLocators(database);
     LoadAppLocators(database);
     LoadIniLocators(database);
     LoadDirFileLocators(database);
     LoadApplicationSearch(database);
     LoadUserDefinedTables(database);
     LoadDirectories(database);
     LoadComponents(database, ref fileSequenceNumber);
     LoadDialogData(database);
     LoadDialogControlData(database);
     LoadDialogControlConditionData(database);
     LoadDialogControlEventData(database);
     LoadRegistry(database);
     LoadTypeLibs(database);
     LoadIconData(database);
     LoadShortcutData(database);
     LoadBinaryData(database);
     LoadCustomAction(database);
     LoadSequence(database);
     LoadActionText(database);
     LoadAppMappings(database);
     LoadUrlProperties(database);
     LoadVDirProperties(database);
     LoadAppRootCreate(database);
     LoadIISDirectoryProperties(database);
     LoadEnvironmentVariables(database);
     LoadSummaryInformation(database);
 }
        /*
         * Common code for the two tasks
         */

        /// <summary>
        /// Sets the sequence number of files to match their
        /// storage order in the cabinet file, after some
        /// files have had their filenames changed to go in
        /// their own component.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="LastSequence">The last file's sequence number.</param>
        protected void ReorderFiles(InstallerDatabase database, ref int LastSequence) {
            if (!Directory.Exists(TempFolderPath))
                return;

            string[] curFileNames = Directory.GetFiles(TempFolderPath, "*.*");

            LastSequence = 1;

            foreach (string curDirFileName in curFileNames) {
                using (InstallerRecordReader reader = database.FindRecords("File", 
                        new InstallerSearchClause("File", Comparison.Equals, Path.GetFileName(curDirFileName)))) {

                    if (reader.Read()) {
                        reader.SetValue(7, LastSequence.ToString());
                        reader.Commit();
                        LastSequence++;
                    } else {
                        throw new BuildException("File " +
                            Path.GetFileName(curDirFileName) +
                            " not found during reordering.");
                    }
                }
            }
        }
        /// <summary>
        /// Adds a directory record to the directories table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="directoryTable">The MSI database view.</param>
        /// <param name="ParentDirectory">The parent directory.</param>
        /// <param name="Directory">This directory's Schema object.</param>
        /// <param name="Depth">The tree depth of this directory.</param>
        private void AddDirectory(InstallerDatabase database, InstallerTable directoryTable,
            string ParentDirectory, MSIDirectory Directory, int Depth) {
            string newParent;
            if (Directory is MSIRootDirectory) {
                newParent = ((MSIRootDirectory)Directory).root;
            } else {
                newParent = ParentDirectory;
            }

            StringBuilder relativePath = new StringBuilder();

            GetRelativePath(database,
                Directory.name, ParentDirectory, Directory.foldername,
                relativePath, directoryTable);

            if (relativePath.ToString().Length != 0) {
                string fullPath = Path.Combine(Path.Combine(Project.BaseDirectory, msi.sourcedir), relativePath.ToString());

                bool createTemp = false;
                DirectoryInfo di = new DirectoryInfo(fullPath);
                DirectoryInfo lastExistingDir = di.Parent;
                if (!di.Exists) {
                    while (!lastExistingDir.Exists) {
                        lastExistingDir = lastExistingDir.Parent;
                    }
                    di.Create();
                    createTemp = true;
                }

                string path = GetShortPath(fullPath) + "|" + Directory.foldername;

                if (createTemp) {
                    while (!di.FullName.Equals(lastExistingDir.FullName)) {
                        di.Delete();
                        di = di.Parent;
                    }
                }

                if (Directory.foldername == ".")
                    path = Directory.foldername;

                Log(Level.Verbose, "\t" +  relativePath.ToString());

                // Insert the Directory
                directoryTable.InsertRecord(Directory.name, newParent, path);

                if (Directory.directory != null) {
                    foreach (MSIDirectory childDirectory in Directory.directory) {
                        int newDepth = Depth + 1;

                        AddDirectory(database, directoryTable,
                            Directory.name, childDirectory, newDepth);
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the sequence tables.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadSequence(InstallerDatabase database) {
            if (msi.sequences == null)
                return;

            Log(Level.Verbose, "Adding Install/Admin Sequences:");

            // Open the sequence tables
            using (InstallerTable
                        installExecuteTable = database.OpenTable("InstallExecuteSequence"),
                        installUITable = database.OpenTable("InstallUISequence"),
                        adminExecuteTable = database.OpenTable("AdminExecuteSequence"),
                        adminUITable = database.OpenTable("AdminUISequence"),
                        advtExecuteTable = database.OpenTable(AdvtExecuteName)) {

                // Add binary data from Task definition
                foreach (MSISequence sequence in msi.sequences) {
                    Log(Level.Verbose, "\t" + sequence.action + " to the " + sequence.type.ToString() + "sequence table.");

                    switch(sequence.type.ToString()) {
                        case "installexecute":
                            installExecuteTable.InsertRecord(sequence.action, sequence.condition, sequence.value);
                            break;
                        case "installui":
                            installUITable.InsertRecord(sequence.action, sequence.condition, sequence.value);
                            break;
                        case "adminexecute":
                            adminExecuteTable.InsertRecord(sequence.action, sequence.condition, sequence.value);
                            break;
                        case "adminui":
                            adminUITable.InsertRecord(sequence.action, sequence.condition, sequence.value);
                            break;
                        case "advtexecute":
                            advtExecuteTable.InsertRecord(sequence.action, sequence.condition, sequence.value);
                            break;

                    }
                }
            }
        }
        /// <summary>
        /// Loads TypeLibs for the TypeLib table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadTypeLibs(InstallerDatabase database) {
            // Open the "TypeLib" Table
            using (InstallerTable typeLibTable = database.OpenTable("TypeLib"), registryTable = database.OpenTable("Registry")) {
                for (int i = 0; i < typeLibRecords.Count; i++) {
                    TypeLibRecord tlbRecord = (TypeLibRecord)typeLibRecords[i];

                    IntPtr pTypeLib = new IntPtr(0);
                    int result = LoadTypeLib(tlbRecord.TypeLibFileName, ref pTypeLib);
                    if (result != 0)
                        continue;

                    UCOMITypeLib typeLib = (UCOMITypeLib)Marshal.GetTypedObjectForIUnknown(
                        pTypeLib, typeof(UCOMITypeLib));
                    if (typeLib == null)
                        continue;

                    int helpContextId;
                    string name, docString, helpFile;

                    typeLib.GetDocumentation(
                        -1, out name, out docString,
                        out helpContextId, out helpFile);

                    IntPtr pTypeLibAttr = new IntPtr(0);
                    typeLib.GetLibAttr(out pTypeLibAttr);

                    TYPELIBATTR typeLibAttr = (TYPELIBATTR)Marshal.PtrToStructure(pTypeLibAttr, typeof(TYPELIBATTR));

                    string tlbCompName = (string)typeLibComponents[Path.GetFileName(tlbRecord.TypeLibFileName)];

                    typeLibTable.InsertRecord("{"+typeLibAttr.guid.ToString().ToUpper()+"}", Marshal.GetTypeLibLcid(typeLib),
                        tlbCompName, 256, docString == null ? name : docString, null, tlbRecord.FeatureName, 0);

                    typeLib.ReleaseTLibAttr(pTypeLibAttr);

                    // If a .NET type library wrapper for an assembly
                    if (tlbRecord.AssemblyName == null)
                        continue;

                    // Get all the types defined in the typelibrary
                    // that are not marked "noncreatable"

                    int typeCount = typeLib.GetTypeInfoCount();
                    for (int j = 0; j < typeCount; j++) {
                        UCOMITypeInfo typeInfo = null;
                        typeLib.GetTypeInfo(j, out typeInfo);

                        if (typeInfo == null)
                            continue;

                        TYPEATTR typeAttr = GetTypeAttributes(typeInfo);

                        if (IsCreatableCoClass(typeAttr)) {
                            if (typeInfo is UCOMITypeInfo2) {
                                string className = GetClassName(typeInfo);

                                if (className != null) {
                                    string clsid = "{" + typeAttr.guid.ToString().ToUpper() + "}";
                                    AddClassToRegistryTable(registryTable, clsid, className, tlbRecord);
                                }
                            }
                        } else if (IsIDispatchInterface(typeAttr)) {
                            string typeName, typeDocString, typeHelpFile;
                            int typeHelpContextId;

                            typeInfo.GetDocumentation(-1, out typeName,
                                out typeDocString, out typeHelpContextId,
                                out typeHelpFile);

                            if (!(typeInfo is UCOMITypeInfo2))
                                continue;

                            UCOMITypeInfo2 typeInfo2 = (UCOMITypeInfo2)typeInfo;
                            if (typeInfo2 == null)
                                continue;

                            object custData;
                            Guid g = new Guid("0F21F359-AB84-41E8-9A78-36D110E6D2F9");
                            typeInfo2.GetCustData(ref g, out custData);

                            if (custData == null)
                                continue;

                            string iid = "{" + typeAttr.guid.ToString().ToUpper() + "}";

                            // Insert the Interface

                            string typeLibComponent = (string)typeLibComponents[Path.GetFileName(tlbRecord.TypeLibFileName)];

                            registryTable.InsertRecord(CreateIdentityGuid(), 0, @"Interface\" + iid,
                                null, typeName, typeLibComponent);

                            registryTable.InsertRecord(CreateIdentityGuid(), 0, @"Interface\" + iid + @"\TypeLib",
                                "Version", "1.0", typeLibComponent);

                            registryTable.InsertRecord(CreateIdentityGuid(), 0, @"Interface\" + iid + @"\TypeLib",
                                null, "{"+typeLibAttr.guid.ToString().ToUpper()+"}", typeLibComponent);

                            registryTable.InsertRecord(CreateIdentityGuid(), 0, @"Interface\" + iid + @"\ProxyStubClsid32",
                                null, "{00020424-0000-0000-C000-000000000046}", typeLibComponent);

                            registryTable.InsertRecord(CreateIdentityGuid(), 0, @"Interface\" + iid + @"\ProxyStubClsid",
                                null, "{00020424-0000-0000-C000-000000000046}", typeLibComponent);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the Components table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="LastSequence">The sequence number of the last file in the .cab</param>
        private void LoadComponents(InstallerDatabase database, ref int LastSequence) {
            if (msi.components == null)
                return;

            Log(Level.Verbose, "Add Files:");

            using (InstallerTable
                        msiAssemblyTable = database.OpenTable("MsiAssembly"),
                        msiAssemblyNameTable = database.OpenTable("MsiAssemblyName"),
                        classTable = database.OpenTable("Class"),
                        progIdTable = database.OpenTable("ProgId"),
                        directoryTable = database.OpenTable("Directory"),
                        componentTable = database.OpenTable("Component"),
                        fileTable = database.OpenTable("File"),
                        featureComponentTable = database.OpenTable("FeatureComponents"),
                        selfRegTable = database.OpenTable("SelfReg")) {

                // Open ModuleComponents table (only exists in MSM archives)
                InstallerTable modComponentTable = null;
                if (database.VerifyTableExistance("ModuleComponents")) {
                    modComponentTable = database.OpenTable("ModuleComponents");
                }

                try {
                    foreach (MSIComponent component in msi.components) {
                        string keyFileName = component.key.file;

                        if (component.fileset == null) {
                            // Make sure the keyfile maps to a valid registry entry
                            if (((XmlElement)_xmlNode).SelectSingleNode("registry/key[@component='" + component.name + "']/value[@id='" + keyFileName + "']") == null) {
                                Log(Level.Warning, "Component '{0}' does not"
                                    + " map to a valid registry key.  Skipping...", 
                                    component.name);
                                continue;
                            }
                        }

                        if (this is MsiCreationCommand)
                            featureComponents.Add(component.name, component.feature);

                        AddModuleComponentVirtual(database, modComponentTable, component.name);

                        if (component.fileset != null) {
                            AddFiles(database, directoryTable, component,
                                fileTable,
                                component.directory, component.name, 
                                ref LastSequence, msiAssemblyTable, msiAssemblyNameTable,
                                componentTable, featureComponentTable, classTable, progIdTable, selfRegTable, modComponentTable);

                            keyFileName = GetKeyFileName(component);
                        }

                        // Insert the Component
                        componentTable.InsertRecord(component.name, component.id.ToUpper(),
                            component.directory, component.attr, component.condition, keyFileName);
                    }

                    // Add featureComponents from Task definition
                    AddFeatureComponents(featureComponentTable);
                } finally {
                    if (modComponentTable != null) {
                        modComponentTable.Close();
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the Registry table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadRegistry(InstallerDatabase database) {
            if (msi.registry == null)
                return;

            Log(Level.Verbose, "Adding Registry Values:");

            using (InstallerTable registryTable = database.OpenTable("Registry")) {
                foreach (MSIRegistryKey key in msi.registry) {
                    int rootKey = GetRegistryRootByName(key.root.ToString());

                    foreach (MSIRegistryKeyValue value in key.value) {
                        if ((value.name == null || value.name == String.Empty) && (value.value == null || value.value == String.Empty) && (value.Value == null))
                            throw new BuildException("Registry value must have a name and/or value specified.");

                        // Insert the Value
                        Log(Level.Verbose, "\t" + GetDisplayablePath(key.path.Replace("}", "}}").Replace("{", "{{")) + @"#" + ((value.name == null || value.name == String.Empty) ? "(Default)":value.name.Replace("}", "}}").Replace("{", "{{")));

                        string keyValue = null;
                        if (value.value != null && value.value != string.Empty) {
                            keyValue = value.value;
                        } else if (value.dword != null && value.dword != string.Empty) {
                            keyValue = "#" + Int32.Parse(value.dword);
                        } else {
                            if (value.Value != null) {
                                string val1 = value.Value.Replace(",", null);
                                string val2 = val1.Replace(" ", null);
                                string val3 = val2.Replace("\n", null);
                                string val4 = val3.Replace("\r", null);
                                keyValue = "#x" + val4;
                            }
                        }

                        registryTable.InsertRecord((value.id != null ? value.id : CreateIdentityGuid()), 
                            rootKey.ToString(), key.path, value.name, keyValue, key.component);
                    }
                }
            }
        }
        /// <summary>
        /// Executes the Task.
        /// </summary>
        /// <remarks>None.</remarks>
        public void Execute() {
            string cabFilePath = Path.Combine(Project.BaseDirectory,
                Path.Combine(msi.sourcedir, CabFileName));
            string errorsTempFile = null;

            try {
                CleanOutput(cabFilePath, TempFolderPath);

                string dest = GetDestinationPath();

                // write the template resource to the destination file
                try {
                    WriteResourceToFile(TemplateResourceName, dest);
                } catch (Exception ex) {
                    throw new BuildException(string.Format(CultureInfo.InvariantCulture, 
                        "Failed writing template to destination file '{0}'.", dest),
                        Location, ex);
                }

                Log(Level.Info, "Building Installer Database '{0}'.", msi.output);

                // Open the Output Database.
                InstallerDatabase database = new InstallerDatabase(dest);
                database.Open();

                if (msi.debug) {
                    errorsTempFile = Path.GetTempFileName();
                    try {
                        // write errors template to file
                        WriteResourceToFile(ErrorsResourceName, errorsTempFile);
                        // if debug is true, transform the error strings in
                        database.ApplyTransform(errorsTempFile);
                    } catch (IOException ex) {
                        throw new BuildException(string.Format(CultureInfo.InvariantCulture, 
                            "Failed writing errors template to '{0}'.", errorsTempFile),
                            Location, ex);
                    }
                }

                int fileSequenceNumber = 0;

                // Load data from the task specification
                LoadCommonDataFromTask(database, ref fileSequenceNumber);
                LoadTypeSpecificDataFromTask(database, fileSequenceNumber);

                // Compress Files
                CreateCabFile(database);

                Log(Level.Info, "Saving Installer Database...");

                // Commit the MSI Database
                database.Close();
            } catch (Exception ex) {
                throw new BuildException(string.Format(CultureInfo.InvariantCulture,
                    "Unable to build Installer database '{0}'.", msi.output), 
                    Location, ex);
            } finally {
                CleanOutput(cabFilePath, TempFolderPath);
                if (errorsTempFile != null) {
                    File.Delete(errorsTempFile);
                }
            }
        }
        /// <summary>
        /// Loads records for the ControlCondtion table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadDialogControlConditionData(InstallerDatabase database) {
            if (msi.controlconditions == null)
                return;

            Log(Level.Verbose, "Adding Dialog Control Conditions for:");

            using (InstallerTable controlConditionTable = database.OpenTable("ControlCondition")) {
                foreach (MSIControlCondition controlCondition in msi.controlconditions) {
                    if (controlCondition.remove) {
                        Log(Level.Verbose, "\tRemoving: " + controlCondition.control);

                        RemoveControlCondition(database, controlCondition);
                    } else {
                        Log(Level.Verbose, "\tAdding:   " + controlCondition.control);

                        controlConditionTable.InsertRecord(controlCondition.dialog, controlCondition.control,
                            controlCondition.action, controlCondition.condition);
                    }
                }
            }
        }
        /// <summary>
        /// Loads records for the Directories table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadDirectories(InstallerDatabase database) {
            if (msi.directories == null)
                return;

            using (InstallerTable directoryTable = database.OpenTable("Directory")) {
                ArrayList directoryList = new ArrayList(msi.directories);

                AddTargetDir(directoryList);
                AddCommonDirectories(directoryList);

                MSIRootDirectory[] directories = new MSIRootDirectory[directoryList.Count];
                directoryList.CopyTo(directories);
                msi.directories = directories;

                int depth = 1;

                Log(Level.Verbose, "Adding Directories:");

                // Add directories from Task definition
                foreach (MSIRootDirectory directory in msi.directories) {
                    AddDirectory(database,
                        directoryTable, null,
                        directory, depth);
                }
            }
        }
        /// <summary>
        /// Loads records for the ControlEvent table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadDialogControlEventData(InstallerDatabase database) {
            if (msi.controlevents == null)
                return;

            Log(Level.Verbose, "Modifying Dialog Control Events:");

            using (InstallerTable controlEventTable = database.OpenTable("ControlEvent")) {
                foreach (MSIControlEvent controlEvent in msi.controlevents) {
                    Log(Level.Verbose, "\t{0}\tControl: {1}\tEvent: {2}", 
                        (controlEvent.remove ? "Removing" : "Adding"), controlEvent.control, controlEvent.name);

                    if (controlEvent.remove) {
                        RemoveControlEvent(database, controlEvent);
                    } else {
                        controlEventTable.InsertRecord(controlEvent.dialog, controlEvent.control,
                            controlEvent.name, controlEvent.argument, controlEvent.condition, controlEvent.order);
                    }
                }
            }
        }
        /// <summary>
        /// Retrieves the relative path of a file based on
        /// the component it belongs to and its entry in
        /// the MSI directory table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        /// <param name="Name">The Name of the Folder</param>
        /// <param name="Parent">The Parent of the Folder</param>
        /// <param name="Default">The Relative Filesystem Path of the Folder</param>
        /// <param name="Path">The Path to the Folder from previous calls.</param>
        /// <param name="directoryTable">The MSI database view.</param>
        private void GetRelativePath(
            InstallerDatabase database,
            string Name,
            string Parent,
            string Default,
            StringBuilder Path,
            InstallerTable directoryTable) {
            if (Name == "TARGETDIR") {
                return;
            }

            for (int i = 0; i < commonFolderNames.Length; i++) {
                if (Name == commonFolderNames[i]) {
                    return;
                }
            }

            if (msi.directories != null) {
                ArrayList directoryList = new ArrayList();
                foreach(MSIRootDirectory directory in msi.directories) {
                    directoryList.Add(directory);
                }

                if (msi.properties != null) {
                    foreach (property property in msi.properties) {
                        if (Name == property.name) {
                            MSIDirectory directory = FindDirectory(Name);
                            if (directory == null) {
                                MSIRootDirectory propDirectory = new MSIRootDirectory();
                                propDirectory.name = Name;
                                propDirectory.root = "TARGETDIR";
                                propDirectory.foldername = ".";

                                directoryList.Add(propDirectory);

                                MSIRootDirectory[] rootDirs = new MSIRootDirectory[directoryList.Count];
                                directoryList.CopyTo(rootDirs);

                                msi.directories = rootDirs;
                            }

                            return;
                        }
                    }
                }
                if (Path.Length > 0) {
                    Path.Insert(0, @"\");
                }

                Path.Insert(0, Default);
                if (Parent != null) {
                    MSIDirectory PathInfo = FindDirectory(Parent);

                    if (PathInfo == null && msi.properties != null) {
                        foreach (property property in msi.properties) {
                            if (Parent == property.name) {
                                MSIRootDirectory directory = new MSIRootDirectory();
                                directory.name = Parent;
                                directory.root = "TARGETDIR";
                                directory.foldername = ".";

                                directoryList.Add(directory);

                                MSIRootDirectory[] rootDirs = new MSIRootDirectory[directoryList.Count];
                                directoryList.CopyTo(rootDirs);

                                msi.directories = rootDirs;

                                // Insert the Directory that is a Property
                                directoryTable.InsertRecord(Parent, "TARGETDIR", ".");

                                PathInfo = directory;

                                break;
                            }
                        }
                    }

                    string newParent = null;
                    if (PathInfo is MSIRootDirectory) {
                        newParent = ((MSIRootDirectory)PathInfo).root;
                    }
                    else {
                        newParent = FindParent(Parent);
                    }

                    GetRelativePath(database,
                        Parent, newParent,
                        PathInfo.foldername, Path, directoryTable);
                }
            }

        }
        private void RemoveControlEvent(InstallerDatabase database, MSIControlEvent controlEvent) {
            // Search for a record using all required attributes
            using (InstallerRecordReader reader = database.FindRecords("ControlEvent", 
                       new InstallerSearchClause("Dialog_", Comparison.Equals, controlEvent.dialog),
                       new InstallerSearchClause("Control_", Comparison.Equals, controlEvent.control),
                       new InstallerSearchClause("Event", Comparison.Equals, controlEvent.name),
                       new InstallerSearchClause("Argument", Comparison.Equals, controlEvent.argument),
                       new InstallerSearchClause("Condition", Comparison.Equals, controlEvent.condition))) {

                if (reader.Read()) {
                    // If the record is found, delete it
                    reader.DeleteCurrentRecord();
                } else {
                    throw new BuildException(string.Format(CultureInfo.InvariantCulture, 
                        "ControlEvent not found for removal: Dialog={0}, Control={1}, Event={2}, Argument={3}, Condition={4}.",
                        controlEvent.dialog, controlEvent.control, controlEvent.name, controlEvent.argument, controlEvent.condition), Location);
                }
            }
        }
        /// <summary>
        /// Loads environment variables for the Environment table.
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadEnvironmentVariables(InstallerDatabase database) {
            if (msi.environment == null)
                return;

            using (InstallerTable envTable = database.OpenTable("Environment")) {
                foreach (MSIVariable variable in msi.environment) {
                    // Insert the Varible
                    string environmentValue = null;
                    if (variable.append != null && variable.append != string.Empty) {
                        environmentValue = "[~];" + variable.append;
                    }
                    envTable.InsertRecord(CreateIdentityGuid(), variable.name, 
                        environmentValue, variable.component);
                }
            }
        }
        /// <summary>
        /// Loads records for the CustomAction table
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadCustomAction(InstallerDatabase database) {
            if (msi.customactions == null)
                return;

            Log(Level.Verbose, "Adding Custom Actions:");

            using (InstallerTable customActionTable = database.OpenTable("CustomAction")) {
                foreach (MSICustomAction customAction in msi.customactions) {
                    Log(Level.Verbose, "\t" + customAction.action);

                    // Insert the record into the table
                    customActionTable.InsertRecord(customAction.action, customAction.type,
                        customAction.source, customAction.target);
                }
            }
        }
        /// <summary>
        /// Loads records for the RegLocator table
        /// </summary>
        /// <param name="database">The MSI database.</param>
        private void LoadRegistryLocators(InstallerDatabase database) {
            if (msi.search == null || msi.search.registry == null)
                return;
                
            Log(Level.Verbose, "Adding Registry Search Locators:");

            foreach (searchRegistry regKey in msi.search.registry) {
                int rootKey = GetRegistryRootByName(regKey.root.ToString());

                if (regKey.value == null)
                    continue;

                foreach (searchRegistryValue value in regKey.value) {
                    string signature = "SIG_" + value.setproperty;
                    int msidbLocatorTypeRawValue = 1;
                    switch (regKey.type) {
                        case MSILocatorTypeDirFileReg64.directory:
                            msidbLocatorTypeRawValue = 0;
                            break;
                        case MSILocatorTypeDirFileReg64.file:
                            msidbLocatorTypeRawValue = 1;
                            break;
                        case MSILocatorTypeDirFileReg64.registry:
                            msidbLocatorTypeRawValue = 2;
                            break;
                        case MSILocatorTypeDirFileReg64.Item64bit:
                            msidbLocatorTypeRawValue = 16;
                            break;
                        }

                    // Select the "RegLocator" Table
                    using (InstallerTable regLocatorTable = database.OpenTable("RegLocator")) {
                    // Insert the signature to the RegLocator Table
                        regLocatorTable.InsertRecord(signature, rootKey.ToString(), regKey.path,
                            value.name, msidbLocatorTypeRawValue);

                        Log(Level.Verbose, "\t" + GetDisplayablePath(regKey.path.Replace("}", "}}").Replace("{", "{{")) + @"#" + ((value.name == null) ? string.Empty : value.name.Replace("}", "}}").Replace("{", "{{")));
                    }
                }                        
            }
        }
 public InstallerTable(View view, InstallerDatabase database)
 {
     _view     = view;
     _database = database;
 }