Example #1
0
        /// <summary>
        /// Adds a file media information object to collection.
        /// </summary>
        /// <param name="fileMediaInfo">File media information to add to the collection.</param>
        public void Add(FileMediaInformation fileMediaInfo)
        {
            if (null == fileMediaInfo)
            {
                throw new ArgumentNullException("fileMediaInfo");
            }

            this.hashTable.Add(fileMediaInfo.FileId, fileMediaInfo);
            this.arrayList.Add(fileMediaInfo);
        }
Example #2
0
        /// <summary>
        /// Compares the object to another object.
        /// </summary>
        /// <param name="obj">Object to compare against.</param>
        /// <returns>compared value.</returns>
        public int CompareTo(object obj)
        {
            FileMediaInformation fmi = obj as FileMediaInformation;

            if (null == fmi)
            {
                throw new ArgumentException("object is not a FileMediaInformation");
            }

            int compared = this.mediaId - fmi.mediaId;

            if (0 == compared)
            {
                compared = this.patchGroup - fmi.patchGroup;

                if (0 == compared)
                {
                    compared = this.rowNumber - fmi.rowNumber;
                }
            }

            return(compared);
        }
        /// <summary>
        /// Adds a file media information object to collection.
        /// </summary>
        /// <param name="fileMediaInfo">File media information to add to the collection.</param>
        public void Add(FileMediaInformation fileMediaInfo)
        {
            if (null == fileMediaInfo)
            {
                throw new ArgumentNullException("fileMediaInfo");
            }

            this.hashTable.Add(fileMediaInfo.FileId, fileMediaInfo);
            this.arrayList.Add(fileMediaInfo);
        }
        /// <summary>
        /// Processes an XmlReader and builds up the file media information object.
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <returns>File media information object.</returns>
        internal static FileMediaInformation Parse(XmlReader reader)
        {
            Debug.Assert("fileMediaInformation" == reader.LocalName);
            string fileId = null;
            string directoryId = null;
            int mediaId = -1;
            string srcPath = null;
            int rowNumber = -1;
            bool containedInModule = false;
            int patchGroup = -1;
            int sequence = -1;
            FileCompressionValue fileCompression = FileCompressionValue.NotSpecified;
            bool empty = reader.IsEmptyElement;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                    case "fileId":
                        fileId = reader.Value;
                        break;
                    case "directoryId":
                        directoryId = reader.Value;
                        break;
                    case "mediaId":
                        mediaId = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                        break;
                    case "srcPath":
                        srcPath = reader.Value;
                        break;
                    case "rowNumber":
                        rowNumber = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                        break;
                    case "inModule":
                        containedInModule = Common.IsYes(reader.Value, null, "fileMediaInformation", "inModule", fileId);
                        break;
                    case "patchGroup":
                        patchGroup = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                        break;
                    case "sequence":
                        sequence = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                        break;
                    case "fileCompression":
                        switch (reader.Value)
                        {
                            case "NotSpecified":
                                fileCompression = FileCompressionValue.NotSpecified;
                                break;
                            case "No":
                                fileCompression = FileCompressionValue.No;
                                break;
                            case "Yes":
                                fileCompression = FileCompressionValue.Yes;
                                break;
                            default:
                                throw new WixParseException(String.Format("The fileMediaInformation/@fileCompression attribute contains an unexpected value '{0}'.", reader.Value));
                        }
                        break;
                    default:
                        throw new WixParseException(String.Format("The fileMediaInformation element contains an unexpected attribute {0}.", reader.Name));
                }
            }
            if (null == fileId)
            {
                throw new WixParseException("The fileMediaInformation/@fileId attribute was not found; it is required.");
            }
            if (null == directoryId)
            {
                throw new WixParseException("The fileMediaInformation/@directoryId attribute was not found; it is required.");
            }

            if (!empty)
            {
                throw new WixParseException("The fileMediaInformation element contains text or other elements; it cannot.");
            }

            FileMediaInformation fmi = new FileMediaInformation(fileId, directoryId, mediaId, srcPath, rowNumber, fileCompression, null, patchGroup);
            fmi.containedInModule = containedInModule;
            fmi.sequence = sequence;
            return fmi;
        }
Example #5
0
        /// <summary>
        /// Processes an XmlReader and builds up the file media information object.
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <returns>File media information object.</returns>
        internal static FileMediaInformation Parse(XmlReader reader)
        {
            Debug.Assert("fileMediaInformation" == reader.LocalName);
            string fileId                        = null;
            string directoryId                   = null;
            int    mediaId                       = -1;
            string srcPath                       = null;
            int    rowNumber                     = -1;
            bool   containedInModule             = false;
            int    patchGroup                    = -1;
            int    sequence                      = -1;
            FileCompressionValue fileCompression = FileCompressionValue.NotSpecified;
            bool empty = reader.IsEmptyElement;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                case "fileId":
                    fileId = reader.Value;
                    break;

                case "directoryId":
                    directoryId = reader.Value;
                    break;

                case "mediaId":
                    mediaId = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                    break;

                case "srcPath":
                    srcPath = reader.Value;
                    break;

                case "rowNumber":
                    rowNumber = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                    break;

                case "inModule":
                    containedInModule = Common.IsYes(reader.Value, null, "fileMediaInformation", "inModule", fileId);
                    break;

                case "patchGroup":
                    patchGroup = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                    break;

                case "sequence":
                    sequence = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                    break;

                case "fileCompression":
                    switch (reader.Value)
                    {
                    case "NotSpecified":
                        fileCompression = FileCompressionValue.NotSpecified;
                        break;

                    case "No":
                        fileCompression = FileCompressionValue.No;
                        break;

                    case "Yes":
                        fileCompression = FileCompressionValue.Yes;
                        break;

                    default:
                        throw new WixParseException(String.Format("The fileMediaInformation/@fileCompression attribute contains an unexpected value '{0}'.", reader.Value));
                    }
                    break;

                default:
                    throw new WixParseException(String.Format("The fileMediaInformation element contains an unexpected attribute {0}.", reader.Name));
                }
            }
            if (null == fileId)
            {
                throw new WixParseException("The fileMediaInformation/@fileId attribute was not found; it is required.");
            }
            if (null == directoryId)
            {
                throw new WixParseException("The fileMediaInformation/@directoryId attribute was not found; it is required.");
            }

            if (!empty)
            {
                throw new WixParseException("The fileMediaInformation element contains text or other elements; it cannot.");
            }

            FileMediaInformation fmi = new FileMediaInformation(fileId, directoryId, mediaId, srcPath, rowNumber, fileCompression, null, patchGroup);

            fmi.containedInModule = containedInModule;
            fmi.sequence          = sequence;
            return(fmi);
        }
Example #6
0
        /// <summary>
        /// Processes an XmlReader and builds up the output object.
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <param name="suppressVersionCheck">Suppresses wix.dll version mismatch check.</param>
        /// <param name="path">The path to display in an error message.</param>
        /// <returns>The Output represented by the Xml.</returns>
        private static Output Parse(XmlReader reader, bool suppressVersionCheck, string path)
        {
            Debug.Assert("wixOutput" == reader.LocalName);

            Output output = new Output();

            output.path = path;
            string      entrySectionId = null;
            SectionType sectionType    = SectionType.Unknown;
            Version     objVersion     = null;
            bool        empty          = reader.IsEmptyElement;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                case "type":
                    switch (reader.Value)
                    {
                    case "Module":
                        output.type = OutputType.Module;
                        sectionType = SectionType.Module;
                        break;

                    case "Product":
                        output.type = OutputType.Product;
                        sectionType = SectionType.Product;
                        break;

                    case "PatchCreation":
                        output.type = OutputType.PatchCreation;
                        sectionType = SectionType.PatchCreation;
                        break;

                    default:
                        throw new WixParseException(String.Format("The wixOutput/@type attribute contains an unexpected value '{0}'.", reader.Value));
                    }
                    break;

                case "codepage":
                    output.codepage = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat);
                    break;

                case "compressed":
                    output.compressed = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null);
                    break;

                case "longFileNames":
                    output.longFileNames = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null);
                    break;

                case "entrySectionId":
                    entrySectionId = reader.Value;
                    break;

                case "moduleGuid":
                    output.moduleGuid = reader.Value;
                    break;

                case "output":
                    output.path = reader.Value;
                    break;

                case "suppressAdminSequence":
                    output.suppressAdminSequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null);
                    break;

                case "suppressAdvertiseSequence":
                    output.suppressAdvertiseSequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null);
                    break;

                case "suppressUISequence":
                    output.suppressUISequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null);
                    break;

                case "version":
                    objVersion = new Version(reader.Value);
                    break;

                case "xmlns":
                    break;

                default:
                    throw new WixParseException(String.Format("The wixOutput element contains an unexpected attribute {0}.", reader.Name));
                }
            }
            if (null == entrySectionId)
            {
                throw new WixParseException("The wixOutput/@entrySectionId attribute was not found; it is required.");
            }
            if (null != objVersion && !suppressVersionCheck)
            {
                Version currentVersion = Common.OutputFormatVersion;
                if (0 != currentVersion.CompareTo(objVersion))
                {
                    throw new WixVersionMismatchException(currentVersion, objVersion, "Output", output.Path);
                }
            }

            // create a section for all the rows to belong to
            Intermediate intermediate = new Intermediate();

            output.entrySection = new Section(intermediate, entrySectionId, sectionType, output.codepage);

            // loop through the rest of the xml building up the Output object
            if (!empty)
            {
                bool done = false;

                // loop through all the fields in a row
                while (!done && reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.LocalName)
                        {
                        case "outputTable":
                            output.outputTables.Add(OutputTable.Parse(reader, output.entrySection));
                            break;

                        case "importStream":
                            output.importStreams.Add(ImportStream.Parse(reader));
                            break;

                        case "componentsToFeatures":
                        case "featuresToFeatures":
                        case "modulesToFeatures":
                            ParseConnectToFeatures(output, reader);
                            break;

                        case "merge":
                            ParseMerge(output, reader);
                            break;

                        case "fileMediaInformation":
                            output.fileMediaInfoCollection.Add(FileMediaInformation.Parse(reader));
                            break;

                        case "media":
                            ParseMedia(output, reader);
                            break;

                        default:
                            throw new WixParseException(String.Format("The wixOutput element contains an unexpected child element {0}.", reader.Name));
                        }
                        break;

                    case XmlNodeType.EndElement:
                        done = true;
                        break;
                    }
                }

                if (!done)
                {
                    throw new WixParseException("Missing end element while processing the wixOutput element.");
                }
            }

            return(output);
        }
Example #7
0
        /// <summary>
        /// Update several msi tables with data contained in files references in the File table.
        /// </summary>
        /// <remarks>
        /// For versioned files, update the file version and language in the File table.  For
        /// unversioned files, add a row to the MsiFileHash table for the file.  For assembly
        /// files, add a row to the MsiAssembly table and add AssemblyName information by adding
        /// MsiAssemblyName rows.
        /// </remarks>
        /// <param name="output">Internal representation of the msi database to operate upon.</param>
        private void UpdateFileInformation(Output output)
        {
            OutputTable mergeTable = output.OutputTables["Merge"];
            if (null != mergeTable)
            {
                foreach (OutputRow outputRow in mergeTable.OutputRows)
                {
                    MergeRow mergeRow = (MergeRow)outputRow.Row;
                    string moduleFile = null;
                    try
                    {
                        moduleFile = this.extension.FileResolutionHandler(mergeRow.SourceFile, FileResolutionType.Module);
                    }
                    catch (WixFileNotFoundException wfnfe)
                    {
                        this.OnMessage(WixErrors.BinderExtensionMissingFile(null, ErrorLevel.Normal, wfnfe.Message));
                        continue;
                    }

                    output.Modules.Add(mergeRow);
                    try
                    {
                        // read the module's File table to get its FileMediaInformation entries
                        using (Database db = new Database(moduleFile, OpenDatabase.ReadOnly))
                        {
                            mergeRow.HasFiles = false;

                            if (db.TableExists("File") && db.TableExists("Component"))
                            {
                                Hashtable uniqueModuleFileIdentifiers = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();

                                using (View view = db.OpenExecuteView("SELECT `File`, `Directory_` FROM `File`, `Component` WHERE `Component_`=`Component`"))
                                {
                                    Record record;
                                    while (view.Fetch(out record))
                                    {
                                        FileMediaInformation fileMediaInformation = new FileMediaInformation(record[1], record[2], mergeRow.DiskId, String.Concat(this.tempFiles.BasePath, Path.DirectorySeparatorChar, "MergeId.", mergeRow.Id.GetHashCode().ToString("X4", CultureInfo.InvariantCulture.NumberFormat), Path.DirectorySeparatorChar, record[1]), mergeRow.Number, mergeRow.FileCompression, moduleFile, -1);
                                        FileMediaInformation otherFileMediaInformation = output.FileMediaInformationCollection[fileMediaInformation.FileId];
                                        string collidingModuleFileIdentifier = (string)uniqueModuleFileIdentifiers[fileMediaInformation.FileId];

                                        if (null == otherFileMediaInformation && null == collidingModuleFileIdentifier)
                                        {
                                            output.FileMediaInformationCollection.Add(fileMediaInformation);

                                            // keep track of file identifiers in this merge module
                                            uniqueModuleFileIdentifiers.Add(fileMediaInformation.FileId, fileMediaInformation.FileId);
                                        }
                                        else // collision(s) detected
                                        {
                                            // case-sensitive collision with another merge module or a user-authored file identifier
                                            if (null != otherFileMediaInformation)
                                            {
                                                this.OnMessage(WixErrors.DuplicateModuleFileIdentifier(mergeRow.SourceLineNumbers, mergeRow.Id, fileMediaInformation.FileId));
                                            }

                                            // case-insensitive collision with another file identifier in the same merge module
                                            if (null != collidingModuleFileIdentifier)
                                            {
                                                this.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(mergeRow.SourceLineNumbers, mergeRow.Id, fileMediaInformation.FileId, collidingModuleFileIdentifier));
                                            }
                                        }

                                        mergeRow.HasFiles = true;
                                    }
                                }
                            }
                        }
                    }
                    catch (FileNotFoundException fnfe)
                    {
                        throw new WixFileNotFoundException(null, moduleFile, fnfe);
                    }
                    catch (IOException ioe)
                    {
                        throw new WixMergeModuleOpenException(mergeRow.SourceLineNumbers, mergeRow.Id, moduleFile, ioe);
                    }
                }
            }

            // calculate sequence numbers and media disk id layout for all file media information objects
            if (OutputType.Module == output.Type)
            {
                int lastSequence = 0;
                foreach (FileMediaInformation fmi in output.FileMediaInformationCollection)
                {
                    fmi.Modularize(output.ModularizationGuid);
                    fmi.Sequence = ++lastSequence;
                }
            }
            else
            {
                int lastSequence = 0;
                MediaRow mediaRow = null;
                output.FileMediaInformationCollection.Sort();
                SortedList patchGroups = new SortedList();

                // sequence the non-patch-added files
                foreach (FileMediaInformation fmi in output.FileMediaInformationCollection)
                {
                    if (null == mediaRow)
                    {
                        mediaRow = output.MediaRows[fmi.Media];
                    }
                    else if (mediaRow.DiskId != fmi.Media)
                    {
                        mediaRow.LastSequence = lastSequence;
                        mediaRow = output.MediaRows[fmi.Media];
                    }

                    if (0 < fmi.PatchGroup)
                    {
                        ArrayList patchGroup = (ArrayList)patchGroups[fmi.PatchGroup];

                        if (null == patchGroup)
                        {
                            patchGroup = new ArrayList();
                            patchGroups.Add(fmi.PatchGroup, patchGroup);
                        }

                        patchGroup.Add(fmi);
                    }
                    else
                    {
                        fmi.Sequence = ++lastSequence;
                    }
                }
                if (null != mediaRow)
                {
                    mediaRow.LastSequence = lastSequence;
                    mediaRow = null;
                }

                // sequence the patch-added files
                foreach (ArrayList patchGroup in patchGroups.Values)
                {
                    foreach (FileMediaInformation fmi in patchGroup)
                    {
                        if (null == mediaRow)
                        {
                            mediaRow = output.MediaRows[fmi.Media];
                        }
                        else if (mediaRow.DiskId != fmi.Media)
                        {
                            mediaRow.LastSequence = lastSequence;
                            mediaRow = output.MediaRows[fmi.Media];
                        }

                        fmi.Sequence = ++lastSequence;
                    }
                }
                if (null != mediaRow)
                {
                    mediaRow.LastSequence = lastSequence;
                }
            }

            // copy the special media rows back to the real media table
            if (0 < output.MediaRows.Count)
            {
                OutputTable mediaTable = Common.EnsureOutputTable(output, this.tableDefinitions["Media"]);

                foreach (MediaRow mediaRow in output.MediaRows)
                {
                    mediaTable.OutputRows.Add(new OutputRow(mediaRow));
                }
            }

            OutputTable fileTable = output.OutputTables["File"];
            if (null == fileTable)   // no work to do
            {
                return;
            }

            foreach (OutputRow outputRow in fileTable.OutputRows)
            {
                FileRow fileRow = outputRow.Row as FileRow;
                if (null == fileRow)
                {
                    throw new ApplicationException("Expected FileRow");
                }

                // copy the sequence number from the file media information to the file table
                fileRow.Sequence = output.FileMediaInformationCollection[fileRow.File].Sequence;

                string src = fileRow.Source;
                FileInfo fileInfo = null;

                if (!this.suppressFileHashAndInfo || (!this.suppressAssemblies && FileAssemblyType.NotAnAssembly != fileRow.AssemblyType))
                {
                    try
                    {
                        src = this.extension.FileResolutionHandler(fileRow.Source, FileResolutionType.File);
                    }
                    catch (WixFileNotFoundException wfnfe)
                    {
                        this.OnMessage(WixErrors.BinderExtensionMissingFile(fileRow.SourceLineNumbers, ErrorLevel.Normal, wfnfe.Message));
                        continue;
                    }

                    try
                    {
                        fileInfo = new FileInfo(src);
                    }
                    catch (ArgumentException)
                    {
                        this.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, ErrorLevel.Normal, src));
                        continue;
                    }
                    catch (PathTooLongException)
                    {
                        this.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, ErrorLevel.Normal, src));
                        continue;
                    }
                    catch (NotSupportedException)
                    {
                        this.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, ErrorLevel.Normal, src));
                        continue;
                    }
                }

                if (!this.suppressFileHashAndInfo)
                {
                    if (fileInfo.Exists)
                    {
                        string version;
                        string language;

                        fileRow.FileSize = fileInfo.Length;
                        try
                        {
                            MsiBase.FileVersion(fileInfo.FullName, out version, out language);
                        }
                        catch (FileNotFoundException e)
                        {
                            throw new WixFileNotFoundException(null, fileInfo.FullName, e);   // TODO: find a way to get the sourceFile (instead of null)
                        }

                        if (0 == version.Length && 0 == language.Length)   // unversioned files have their hashes added to the MsiFileHash table
                        {
                            int[] hash;
                            try
                            {
                                MsiBase.GetFileHash(fileInfo.FullName, 0, out hash);
                            }
                            catch (FileNotFoundException e)
                            {
                                throw new WixFileNotFoundException(null, fileInfo.FullName, e);   // TODO: find a way to get the sourceFile (instead of null)
                            }

                            OutputTable outputHashTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiFileHash"]);
                            Row hashRow = new Row(outputHashTable.TableDefinition);
                            hashRow[0] = fileRow.File;
                            hashRow[1] = 0;
                            hashRow[2] = hash[0];
                            hashRow[3] = hash[1];
                            hashRow[4] = hash[2];
                            hashRow[5] = hash[3];
                            outputHashTable.OutputRows.Add(new OutputRow(hashRow));
                        }
                        else // update the file row with the version and language information
                        {
                            fileRow.Version = version;
                            fileRow.Language = language;
                        }
                    }
                    else
                    {
                        this.OnMessage(WixErrors.CannotFindFile(fileRow.SourceLineNumbers, ErrorLevel.Normal, fileRow.File, fileRow.FileName, src));
                    }
                }

                // if we're not suppressing automagically grabbing assembly information and this is a
                // CLR assembly, load the assembly and get the assembly name information
                if (!this.suppressAssemblies)
                {
                    if (FileAssemblyType.DotNetAssembly == fileRow.AssemblyType)
                    {
                        StringDictionary assemblyNameValues = new StringDictionary();

                        // under CLR 2.0, use a more robust method of gathering AssemblyName information
                        if (2 <= Environment.Version.Major)
                        {
                            CLRInterop.IReferenceIdentity referenceIdentity = null;
                            Guid referenceIdentityGuid = CLRInterop.ReferenceIdentityGuid;

                            if (0 == CLRInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity))
                            {
                                if (null != referenceIdentity)
                                {
                                    string culture = referenceIdentity.GetAttribute(null, "Culture");
                                    if (null != culture)
                                    {
                                        assemblyNameValues.Add("Culture", culture);
                                    }

                                    string name = referenceIdentity.GetAttribute(null, "Name");
                                    if (null != name)
                                    {
                                        assemblyNameValues.Add("Name", name);
                                    }

                                    string processorArchitecture = referenceIdentity.GetAttribute(null, "ProcessorArchitecture");
                                    if (null != processorArchitecture)
                                    {
                                        assemblyNameValues.Add("ProcessorArchitecture", processorArchitecture);
                                    }

                                    string publicKeyToken = referenceIdentity.GetAttribute(null, "PublicKeyToken");
                                    if (null != publicKeyToken)
                                    {
                                        assemblyNameValues.Add("PublicKeyToken", publicKeyToken.ToUpper(CultureInfo.InvariantCulture));
                                    }

                                    string version = referenceIdentity.GetAttribute(null, "Version");
                                    if (null != version)
                                    {
                                        assemblyNameValues.Add("Version", version);
                                    }
                                }
                            }
                        }
                        else
                        {
                            AssemblyName assemblyName = null;
                            try
                            {
                                assemblyName = AssemblyName.GetAssemblyName(fileInfo.FullName);

                                if (null != assemblyName.CultureInfo)
                                {
                                    assemblyNameValues.Add("Culture", assemblyName.CultureInfo.ToString());
                                }

                                if (null != assemblyName.Name)
                                {
                                    assemblyNameValues.Add("Name", assemblyName.Name);
                                }

                                byte[] publicKey = assemblyName.GetPublicKeyToken();
                                if (null != publicKey && 0 < publicKey.Length)
                                {
                                    StringBuilder sb = new StringBuilder();
                                    for (int i = 0; i < publicKey.GetLength(0); ++i)
                                    {
                                        sb.AppendFormat("{0:X2}", publicKey[i]);
                                    }
                                    assemblyNameValues.Add("PublicKeyToken", sb.ToString());
                                }

                                if (null != assemblyName.Version)
                                {
                                    assemblyNameValues.Add("Version", assemblyName.Version.ToString());
                                }
                            }
                            catch (FileNotFoundException fnfe)
                            {
                                throw new WixFileNotFoundException(fileRow.SourceLineNumbers, fileInfo.FullName, fnfe);
                            }
                            catch (Exception e)
                            {
                                if (e is NullReferenceException || e is SEHException)
                                {
                                    throw;
                                }
                                else
                                {
                                    throw new WixInvalidAssemblyException(fileRow.SourceLineNumbers, fileInfo, e);
                                }
                            }
                        }

                        OutputTable assemblyNameOutputTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiAssemblyName"]);
                        if (assemblyNameValues.ContainsKey("name"))
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "name", assemblyNameValues["name"]);
                        }

                        string fileVersion = null;
                        if (this.setMsiAssemblyNameFileVersion)
                        {
                            string language;

                            MsiBase.FileVersion(fileInfo.FullName, out fileVersion, out language);
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "fileVersion", fileVersion);
                        }

                        if (assemblyNameValues.ContainsKey("version"))
                        {
                            string assemblyVersion = assemblyNameValues["version"];

                            // there is a bug in fusion that requires the assembly's "version" attribute
                            // to be equal to or longer than the "fileVersion" in length when its present;
                            // the workaround is to prepend zeroes to the last version number in the assembly version
                            if (this.setMsiAssemblyNameFileVersion && null != fileVersion && fileVersion.Length > assemblyVersion.Length)
                            {
                                string padding = new string('0', fileVersion.Length - assemblyVersion.Length);
                                string[] assemblyVersionNumbers = assemblyVersion.Split('.');

                                if (assemblyVersionNumbers.Length > 0)
                                {
                                    assemblyVersionNumbers[assemblyVersionNumbers.Length - 1] = String.Concat(padding, assemblyVersionNumbers[assemblyVersionNumbers.Length - 1]);
                                    assemblyVersion = String.Join(".", assemblyVersionNumbers);
                                }
                            }

                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "version", assemblyVersion);
                        }

                        if (assemblyNameValues.ContainsKey("culture"))
                        {
                            string culture = assemblyNameValues["culture"];
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "culture", (String.Empty == culture ? "neutral" : culture));
                        }

                        if (assemblyNameValues.ContainsKey("publicKeyToken"))
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "publicKeyToken", assemblyNameValues["publicKeyToken"]);
                        }

                        if (null != fileRow.ProcessorArchitecture && 0 < fileRow.ProcessorArchitecture.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "processorArchitecture", fileRow.ProcessorArchitecture);
                        }

                        if (assemblyNameValues.ContainsKey("processorArchitecture"))
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "processorArchitecture", assemblyNameValues["processorArchitecture"]);
                        }
                    }
                    else if (FileAssemblyType.Win32Assembly == fileRow.AssemblyType)
                    {
                        FileRow fileManifestRow = fileRow;

                        // would rather look this up through a data structure rather than
                        // do an order n search through the list of files for every
                        // instance of a win32 assembly.  From what I can find, there
                        // are no indexed data structures available at this point
                        // in the code we're left with this expensive search.
                        foreach (OutputRow manifestOutputRow in fileTable.OutputRows)
                        {
                            fileManifestRow = manifestOutputRow.Row as FileRow;
                            if (fileManifestRow.File == fileRow.AssemblyManifest)
                            {
                                break;
                            }
                        }

                        string type = null;
                        string name = null;
                        string version = null;
                        string processorArchitecture = null;
                        string publicKeyToken = null;

                        // loading the dom is expensive we want more performant APIs than the DOM
                        // Navigator is cheaper than dom.  Perhaps there is a cheaper API still.
                        string manifestSourcePath = null;
                        try
                        {
                            manifestSourcePath = this.extension.FileResolutionHandler(fileManifestRow.Source, FileResolutionType.File);
                        }
                        catch (WixFileNotFoundException wfnfe)
                        {
                            this.OnMessage(WixErrors.BinderExtensionMissingFile(fileRow.SourceLineNumbers, ErrorLevel.Normal, wfnfe.Message));
                            continue;
                        }

                        try
                        {
                            XPathDocument doc = new XPathDocument(manifestSourcePath);
                            XPathNavigator nav = doc.CreateNavigator();
                            nav.MoveToRoot();

                            // this assumes a particular schema for a win32 manifest and does not
                            // provide error checking if the file does not conform to schema.
                            // The fallback case here is that nothing is added to the MsiAssemblyName
                            // table for a out of tollerence Win32 manifest.  Perhaps warnings needed.
                            if (nav.MoveToFirstChild())
                            {
                                while (nav.NodeType != XPathNodeType.Element || nav.Name != "assembly")
                                {
                                    nav.MoveToNext();
                                }
                                if (nav.MoveToFirstChild())
                                {
                                    while (nav.NodeType != XPathNodeType.Element || nav.Name != "assemblyIdentity")
                                    {
                                        nav.MoveToNext();
                                    }
                                    if (nav.MoveToAttribute("type", String.Empty))
                                    {
                                        type = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("name", String.Empty))
                                    {
                                        name = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("version", String.Empty))
                                    {
                                        version = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("processorArchitecture", String.Empty))
                                    {
                                        processorArchitecture = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("publicKeyToken", String.Empty))
                                    {
                                        publicKeyToken = nav.Value;
                                        nav.MoveToParent();
                                    }
                                }
                            }
                        }
                        catch (XmlException xe)
                        {
                            this.OnMessage(WixErrors.InvalidXml(SourceLineNumberCollection.FromFileName(manifestSourcePath), "manifest", xe.Message));
                        }

                        OutputTable assemblyNameOutputTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiAssemblyName"]);
                        if (null != name && 0 < name.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "name", name);
                        }
                        if (null != version && 0 < version.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "version", version);
                        }
                        if (null != type && 0 < type.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "type", type);
                        }
                        if (null != processorArchitecture && 0 < processorArchitecture.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "processorArchitecture", processorArchitecture);
                        }
                        if (null != publicKeyToken && 0 < publicKeyToken.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "publicKeyToken", publicKeyToken);
                        }
                    }
                }
            }
        }