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 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 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);
                    }
                }
            }
        }
Beispiel #6
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);
                    }
                }
            }
        }
Beispiel #7
0
        private void AddFeatureConditions(MSIFeature Feature, InstallerTable conditionTable)
        {
            if (Feature.conditions != null)
            {
                Log(Level.Verbose, "\t\tAdding Feature Conditions...");

                foreach (MSIFeatureCondition featureCondition in Feature.conditions)
                {
                    try {
                        // Insert the feature's condition
                        conditionTable.InsertRecord(Feature.name, featureCondition.level, featureCondition.expression);
                    } catch (Exception ex) {
                        Log(Level.Info, "Error adding feature condition: " + ex.Message);
                    }
                }

                Log(Level.Verbose, "Done");
            }
        }
        /// <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 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 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);
                    }
                }
            }
        }
        private void AddAssemblyManifestRecords(Assembly fileAssembly, InstallerTable msiAssemblyNameTable, string asmCompName) {
            AssemblyName asmName = fileAssembly.GetName();

            string version = asmName.Version.ToString(4);

            AssemblyCultureAttribute[] cultureAttrs =
                (AssemblyCultureAttribute[])fileAssembly.GetCustomAttributes(
                typeof(AssemblyCultureAttribute), true);

            string culture = "neutral";
            if (cultureAttrs.Length > 0) {
                culture = cultureAttrs[0].Culture;
            }

            string publicKey = null;
            byte[] keyToken = asmName.GetPublicKeyToken();
            if (keyToken != null) {
                publicKey = ByteArrayToString(keyToken);
            }

            if (asmName.Name != null && asmName.Name.Length != 0) {
                msiAssemblyNameTable.InsertRecord(asmCompName, "Name", asmName.Name);
            }

            if (version != null && version.Length != 0) {
                msiAssemblyNameTable.InsertRecord(asmCompName, "Version", version);
            }

            if (culture != null && culture.Length != 0) {
                msiAssemblyNameTable.InsertRecord(asmCompName, "Culture", culture);
            }

            if (publicKey != null && publicKey.Length != 0) {
                msiAssemblyNameTable.InsertRecord(asmCompName, "PublicKeyToken", publicKey);
            }
        }
        /// <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());
            }
        }
        /// <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 AddColumnValidation(string tableName, MSITableColumn column, InstallerTable validationTable) {
            string nullability = GetNullability(column);

            string validationCategory = GetValidationCategory(column);

            int minValue;
            bool useMinValue;
            GetMinValue(column, out minValue, out useMinValue);

            int maxValue;
            bool useMaxValue;
            GetMaxValue(column, out maxValue, out useMaxValue);

            try {
                validationTable.InsertRecord(tableName, column.name, nullability,
                    (useMinValue ? (object) minValue : null),
                    (useMaxValue ? (object) maxValue : null), column.keytable,
                    (column.keycolumnSpecified ? (object) column.keycolumn : null),
                    validationCategory, column.set, column.description);
            } catch (Exception) {
                Log(Level.Warning, "_Validation table record already exists for column: " + column.name);
            }
        }
 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));
 }
        private void AddFeatureConditions(MSIFeature Feature, InstallerTable conditionTable) {
            if (Feature.conditions != null) {
                Log(Level.Verbose, "\t\tAdding Feature Conditions...");

                foreach (MSIFeatureCondition featureCondition in Feature.conditions) {
                    try {
                        // Insert the feature's condition
                        conditionTable.InsertRecord(Feature.name, featureCondition.level, featureCondition.expression);
                    } catch (Exception ex) {
                        Log(Level.Info, "Error adding feature condition: " + ex.Message);
                    }
                }

                Log(Level.Verbose, "Done");
            }
        }
        /// <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 AddFeatureComponents(InstallerTable featureComponentTable) {
            IEnumerator keyEnum = featureComponents.Keys.GetEnumerator();

            while (keyEnum.MoveNext()) {
                string component = Properties.ExpandProperties((string)keyEnum.Current, Location);
                string feature = Properties.ExpandProperties((string)featureComponents[component], Location);

                if (feature == null) {
                    throw new BuildException("Component " + component +
                        " mapped to nonexistent feature.");
                }

                // Insert the FeatureComponent
                featureComponentTable.InsertRecord(feature, component);
            }
        }
        /// <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);
                    }
                }
            }
        }
 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));
 }
        private void AddClassToRegistryTable(InstallerTable registryTable, string classGuid, string className, TypeLibRecord tlbRecord) {
            string registryClassIdKeyPart = @"CLSID\" + classGuid + @"\";

            // Insert the Class
            registryTable.InsertRecord(CreateIdentityGuid(), 0, registryClassIdKeyPart + "InprocServer32",
                "Class", className, tlbRecord.AssemblyComponent);

            registryTable.InsertRecord(CreateIdentityGuid(), 0, registryClassIdKeyPart + "InprocServer32",
                "ThreadingModel", "Both", tlbRecord.AssemblyComponent);

            // clr version should have format major.minor.build 
            registryTable.InsertRecord(CreateIdentityGuid(), 0, registryClassIdKeyPart + "InprocServer32",
                "RuntimeVersion", "v"+ Project.TargetFramework.ClrVersion, tlbRecord.AssemblyComponent);

            registryTable.InsertRecord(CreateIdentityGuid(), 0, registryClassIdKeyPart + "InprocServer32",
                "Assembly", tlbRecord.AssemblyName.FullName, tlbRecord.AssemblyComponent);

            registryTable.InsertRecord(CreateIdentityGuid(), 0, registryClassIdKeyPart + "Implemented Categories",
                "+", null, tlbRecord.AssemblyComponent);

            registryTable.InsertRecord(CreateIdentityGuid(), 0, registryClassIdKeyPart + 
                @"Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}",
                "+", null, tlbRecord.AssemblyComponent);
        }
        /// <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++;
                }
            }
        }