Exemplo n.º 1
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <param name="add">Specifies whether to only create the row or add it to the table automatically.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers, bool add)
        {
            Row row;

            switch (this.Name)
            {
            case "BBControl":
                row = new BBControlRow(sourceLineNumbers, this);
                break;

            case "ChainMsiPackage":
                row = new ChainMsiPackageRow(sourceLineNumbers, this);
                break;

            case "Component":
                row = new ComponentRow(sourceLineNumbers, this);
                break;

            case "Control":
                row = new ControlRow(sourceLineNumbers, this);
                break;

            case "File":
                row = new FileRow(sourceLineNumbers, this);
                break;

            case "Media":
                row = new MediaRow(sourceLineNumbers, this);
                break;

            case "PayloadInfo":
                row = new PayloadInfoRow(sourceLineNumbers, this);
                break;

            case "Upgrade":
                row = new UpgradeRow(sourceLineNumbers, this);
                break;

            case "Variable":
                row = new VariableRow(sourceLineNumbers, this);
                break;

            case "WixAction":
                row = new WixActionRow(sourceLineNumbers, this);
                break;

            case "WixApprovedExeForElevation":
                row = new WixApprovedExeForElevationRow(sourceLineNumbers, this);
                break;

            case "WixBundle":
                row = new WixBundleRow(sourceLineNumbers, this);
                break;

            case "WixBundlePatchTargetCode":
                row = new WixBundlePatchTargetCodeRow(sourceLineNumbers, this);
                break;

            case "WixBundleUpdate":
                row = new WixBundleUpdateRow(sourceLineNumbers, this);
                break;

            case "WixCatalog":
                row = new WixCatalogRow(sourceLineNumbers, this);
                break;

            case "WixCommandLine":
                row = new WixCommandLineRow(sourceLineNumbers, this);
                break;

            case "WixComplexReference":
                row = new WixComplexReferenceRow(sourceLineNumbers, this);
                break;

            case "WixFile":
                row = new WixFileRow(sourceLineNumbers, this);
                break;

            case "WixMedia":
                row = new WixMediaRow(sourceLineNumbers, this);
                break;

            case "WixMediaTemplate":
                row = new WixMediaTemplateRow(sourceLineNumbers, this);
                break;

            case "WixMerge":
                row = new WixMergeRow(sourceLineNumbers, this);
                break;

            case "WixProperty":
                row = new WixPropertyRow(sourceLineNumbers, this);
                break;

            case "WixSimpleReference":
                row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                break;

            case "WixUpdateRegistration":
                row = new WixUpdateRegistrationRow(sourceLineNumbers, this);
                break;

            case "WixVariable":
                row = new WixVariableRow(sourceLineNumbers, this);
                break;

            default:
                row = new Row(sourceLineNumbers, this);
                break;
            }

            if (add)
            {
                this.rows.Add(row);
            }

            return(row);
        }
Exemplo n.º 2
0
Arquivo: Binder.cs Projeto: zooba/wix3
        private void UpdateBurnResources(string bundleTempPath, string outputPath, WixBundleRow bundleInfo)
        {
            Microsoft.Deployment.Resources.ResourceCollection resources = new Microsoft.Deployment.Resources.ResourceCollection();
            Microsoft.Deployment.Resources.VersionResource version = new Microsoft.Deployment.Resources.VersionResource("#1", 1033);

            version.Load(bundleTempPath);
            resources.Add(version);

            // Ensure the bundle info provides a full four part version.
            Version fourPartVersion = new Version(bundleInfo.Version);
            int major = (fourPartVersion.Major < 0) ? 0 : fourPartVersion.Major;
            int minor = (fourPartVersion.Minor < 0) ? 0 : fourPartVersion.Minor;
            int build = (fourPartVersion.Build < 0) ? 0 : fourPartVersion.Build;
            int revision = (fourPartVersion.Revision < 0) ? 0 : fourPartVersion.Revision;

            if (UInt16.MaxValue < major || UInt16.MaxValue < minor || UInt16.MaxValue < build || UInt16.MaxValue < revision)
            {
                throw new WixException(WixErrors.InvalidModuleOrBundleVersion(bundleInfo.SourceLineNumbers, "Bundle", bundleInfo.Version));
            }

            fourPartVersion = new Version(major, minor, build, revision);
            version.FileVersion = fourPartVersion;
            version.ProductVersion = fourPartVersion;

            Microsoft.Deployment.Resources.VersionStringTable strings = version[1033];
            strings["LegalCopyright"] = bundleInfo.Copyright;
            strings["OriginalFilename"] = Path.GetFileName(outputPath);
            strings["FileVersion"] = bundleInfo.Version;    // string versions do not have to be four parts.
            strings["ProductVersion"] = bundleInfo.Version; // string versions do not have to be four parts.

            if (!String.IsNullOrEmpty(bundleInfo.Name))
            {
                strings["ProductName"] = bundleInfo.Name;
                strings["FileDescription"] = bundleInfo.Name;
            }

            if (!String.IsNullOrEmpty(bundleInfo.Publisher))
            {
                strings["CompanyName"] = bundleInfo.Publisher;
            }
            else
            {
                strings["CompanyName"] = String.Empty;
            }

            if (!String.IsNullOrEmpty(bundleInfo.IconPath))
            {
                Deployment.Resources.GroupIconResource iconGroup = new Deployment.Resources.GroupIconResource("#1", 1033);
                iconGroup.ReadFromFile(bundleInfo.IconPath);
                resources.Add(iconGroup);

                foreach (Deployment.Resources.Resource icon in iconGroup.Icons)
                {
                    resources.Add(icon);
                }
            }

            if (!String.IsNullOrEmpty(bundleInfo.SplashScreenBitmapPath))
            {
                Deployment.Resources.BitmapResource bitmap = new Deployment.Resources.BitmapResource("#1", 1033);
                bitmap.ReadFromFile(bundleInfo.SplashScreenBitmapPath);
                resources.Add(bitmap);
            }

            resources.Save(bundleTempPath);
        }
Exemplo n.º 3
0
Arquivo: Table.cs Projeto: zooba/wix3
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <param name="add">Specifies whether to only create the row or add it to the table automatically.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers, bool add)
        {
            Row row;

            switch (this.Name)
            {
                case "BBControl":
                    row = new BBControlRow(sourceLineNumbers, this);
                    break;
                case "ChainMsiPackage":
                    row = new ChainMsiPackageRow(sourceLineNumbers, this);
                    break;
                case "Component":
                    row = new ComponentRow(sourceLineNumbers, this);
                    break;
                case "Control":
                    row = new ControlRow(sourceLineNumbers, this);
                    break;
                case "File":
                    row = new FileRow(sourceLineNumbers, this);
                    break;
                case "Media":
                    row = new MediaRow(sourceLineNumbers, this);
                    break;
                case "PayloadInfo":
                    row = new PayloadInfoRow(sourceLineNumbers, this);
                    break;
                case "Upgrade":
                    row = new UpgradeRow(sourceLineNumbers, this);
                    break;
                case "Variable":
                    row = new VariableRow(sourceLineNumbers, this);
                    break;
                case "WixAction":
                    row = new WixActionRow(sourceLineNumbers, this);
                    break;
                case "WixApprovedExeForElevation":
                    row = new WixApprovedExeForElevationRow(sourceLineNumbers, this);
                    break;
                case "WixBundle":
                    row = new WixBundleRow(sourceLineNumbers, this);
                    break;
                case "WixBundlePatchTargetCode":
                    row = new WixBundlePatchTargetCodeRow(sourceLineNumbers, this);
                    break;
                case "WixBundleUpdate":
                    row = new WixBundleUpdateRow(sourceLineNumbers, this);
                    break;
                case "WixCatalog":
                    row = new WixCatalogRow(sourceLineNumbers, this);
                    break;
                case "WixCommandLine":
                    row = new WixCommandLineRow(sourceLineNumbers, this);
                    break;
                case "WixComplexReference":
                    row = new WixComplexReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixFile":
                    row = new WixFileRow(sourceLineNumbers, this);
                    break;
                case "WixMedia":
                    row = new WixMediaRow(sourceLineNumbers, this);
                    break;
                case "WixMediaTemplate":
                    row = new WixMediaTemplateRow(sourceLineNumbers, this);
                    break;
                case "WixMerge":
                    row = new WixMergeRow(sourceLineNumbers, this);
                    break;
                case "WixProperty":
                    row = new WixPropertyRow(sourceLineNumbers, this);
                    break;
                case "WixSimpleReference":
                    row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixUpdateRegistration":
                    row = new WixUpdateRegistrationRow(sourceLineNumbers, this);
                    break;
                case "WixVariable":
                    row = new WixVariableRow(sourceLineNumbers, this);
                    break;

                default:
                    row = new Row(sourceLineNumbers, this);
                    break;
            }

            if (add)
            {
                this.rows.Add(row);
            }

            return row;
        }
Exemplo n.º 4
0
Arquivo: Binder.cs Projeto: zooba/wix3
        /// <summary>
        /// Sets the provider key for the bundle.
        /// </summary>
        /// <param name="bundle">The <see cref="Output"/> object for the bundle.</param>
        /// <param name="bundleInfo">The <see cref="BundleInfo"/> containing the provider key and other information for the bundle.</param>
        private void SetBundleProviderKey(Output bundle, WixBundleRow bundleInfo)
        {
            // From DependencyCommon.cs in the WixDependencyExtension.
            const int ProvidesAttributesBundle = 0x10000;

            Table wixDependencyProviderTable = bundle.Tables["WixDependencyProvider"];
            if (null != wixDependencyProviderTable && 0 < wixDependencyProviderTable.Rows.Count)
            {
                // Search the WixDependencyProvider table for the single bundle provider key.
                foreach (Row wixDependencyProviderRow in wixDependencyProviderTable.Rows)
                {
                    object attributes = wixDependencyProviderRow[5];
                    if (null != attributes && 0 != (ProvidesAttributesBundle & (int)attributes))
                    {
                        bundleInfo.ProviderKey = (string)wixDependencyProviderRow[2];
                        break;
                    }
                }
            }

            // Defaults to the bundle ID as the provider key.
        }
Exemplo n.º 5
0
Arquivo: Binder.cs Projeto: zooba/wix3
        private void PopulateChainInfoTables(Output bundle, WixBundleRow bundleInfo, List<ChainPackageInfo> chainPackages)
        {
            bool hasPerMachineNonPermanentPackages = false;

            foreach (ChainPackageInfo package in chainPackages)
            {
                // Update package scope from bundle scope if default.
                if (YesNoDefaultType.Default == package.PerMachine)
                {
                    package.PerMachine = bundleInfo.PerMachine ? YesNoDefaultType.Yes : YesNoDefaultType.No;
                }

                // Keep track if any per-machine non-permanent packages exist.
                if (YesNoDefaultType.Yes == package.PerMachine && 0 < package.Provides.Count && !package.Permanent)
                {
                    hasPerMachineNonPermanentPackages = true;
                }

                switch (package.ChainPackageType)
                {
                    case Compiler.ChainPackageType.Msi:
                        Table chainMsiPackageTable = bundle.EnsureTable(this.core.TableDefinitions["ChainMsiPackage"]);
                        ChainMsiPackageRow row = (ChainMsiPackageRow)chainMsiPackageTable.CreateRow(null);
                        row.ChainPackage = package.Id;
                        row.ProductCode = package.ProductCode;
                        row.ProductLanguage = Convert.ToInt32(package.Language, CultureInfo.InvariantCulture);
                        row.ProductName = package.DisplayName;
                        row.ProductVersion = package.Version;
                        if (!String.IsNullOrEmpty(package.UpgradeCode))
                        {
                            row.UpgradeCode = package.UpgradeCode;
                        }
                        break;
                    default:
                        break;
                }
            }

            // We will only register packages in the same scope as the bundle.
            // Warn if any packages with providers are in a different scope
            // and not permanent (permanents typically don't need a ref-count).
            if (!bundleInfo.PerMachine && hasPerMachineNonPermanentPackages)
            {
                this.core.OnMessage(WixWarnings.NoPerMachineDependencies());
            }
        }
Exemplo n.º 6
0
Arquivo: Binder.cs Projeto: zooba/wix3
 private void PopulateBundleInfoFromChain(WixBundleRow bundleInfo, List<ChainPackageInfo> chainPackages)
 {
     foreach (ChainPackageInfo package in chainPackages)
     {
         if (bundleInfo.PerMachine && YesNoDefaultType.No == package.PerMachine)
         {
             this.core.OnMessage(WixVerboses.SwitchingToPerUserPackage(package.PackagePayload.FullFileName));
             bundleInfo.PerMachine = false;
         }
     }
 }
Exemplo n.º 7
0
Arquivo: Binder.cs Projeto: zooba/wix3
 private void GenerateBAManifestBundleTables(Output bundle, WixBundleRow bundleInfo)
 {
     Table wixBundlePropertiesTable = bundle.EnsureTable(this.core.TableDefinitions["WixBundleProperties"]);
     Row row = wixBundlePropertiesTable.CreateRow(bundleInfo.SourceLineNumbers);
     row[0] = bundleInfo.Name;
     row[1] = bundleInfo.LogPathVariable;
     row[2] = (YesNoDefaultType.Yes == bundleInfo.Compressed) ? "yes" : "no";
     row[3] = bundleInfo.BundleId.ToString("B");
     row[4] = bundleInfo.UpgradeCode;
     row[5] = bundleInfo.PerMachine ? "yes" : "no";
 }
Exemplo n.º 8
0
Arquivo: Binder.cs Projeto: zooba/wix3
        private void CreateBurnManifest(string outputPath, WixBundleRow bundleInfo, WixBundleUpdateRow updateRow, WixUpdateRegistrationRow updateRegistrationInfo, string path, List<RelatedBundleInfo> allRelatedBundles, List<VariableInfo> allVariables, List<WixSearchInfo> orderedSearches, Dictionary<string, PayloadInfoRow> allPayloads, ChainInfo chain, Dictionary<string, ContainerInfo> containers, Dictionary<string, CatalogInfo> catalogs, Table wixBundleTagTable, List<ApprovedExeForElevation> approvedExesForElevation, Dictionary<string, List<WixCommandLineRow>> commandLinesByPackage)
        {
            string executableName = Path.GetFileName(outputPath);

            using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
            {
                writer.WriteStartDocument();

                writer.WriteStartElement("BurnManifest", BurnCommon.BurnNamespace);

                // Write the condition, if there is one
                if (null != bundleInfo.Condition)
                {
                    writer.WriteElementString("Condition", bundleInfo.Condition);
                }

                // Write the log element if default logging wasn't disabled.
                if (!String.IsNullOrEmpty(bundleInfo.LogPrefix))
                {
                    writer.WriteStartElement("Log");
                    if (!String.IsNullOrEmpty(bundleInfo.LogPathVariable))
                    {
                        writer.WriteAttributeString("PathVariable", bundleInfo.LogPathVariable);
                    }
                    writer.WriteAttributeString("Prefix", bundleInfo.LogPrefix);
                    writer.WriteAttributeString("Extension", bundleInfo.LogExtension);
                    writer.WriteEndElement();
                }

                if (null != updateRow)
                {
                    writer.WriteStartElement("Update");
                    writer.WriteAttributeString("Location", updateRow.Location);
                    writer.WriteEndElement(); // </Update>
                }

                // Write the RelatedBundle elements
                foreach (RelatedBundleInfo relatedBundle in allRelatedBundles)
                {
                    relatedBundle.WriteXml(writer);
                }

                // Write the variables
                foreach (VariableInfo variable in allVariables)
                {
                    variable.WriteXml(writer);
                }

                // Write the searches
                foreach (WixSearchInfo searchinfo in orderedSearches)
                {
                    searchinfo.WriteXml(writer);
                }

                // write the UX element
                writer.WriteStartElement("UX");
                if (!String.IsNullOrEmpty(bundleInfo.SplashScreenBitmapPath))
                {
                    writer.WriteAttributeString("SplashScreen", "yes");
                }

                // write the UX allPayloads...
                List<PayloadInfoRow> uxPayloads = containers[Compiler.BurnUXContainerId].Payloads;
                foreach (PayloadInfoRow payload in uxPayloads)
                {
                    writer.WriteStartElement("Payload");
                    WriteBurnManifestPayloadAttributes(writer, payload, true, this.FileManager, allPayloads);
                    writer.WriteEndElement();
                }

                writer.WriteEndElement();

                // write the catalog elements
                if (catalogs.Count > 0)
                {
                    foreach (CatalogInfo catalog in catalogs.Values)
                    {
                        writer.WriteStartElement("Catalog");
                        writer.WriteAttributeString("Id", catalog.Id);
                        writer.WriteAttributeString("Payload", catalog.PayloadId);
                        writer.WriteEndElement();
                    }
                }

                int attachedContainerIndex = 1; // count starts at one because UX container is "0".
                foreach (ContainerInfo container in containers.Values)
                {
                    if (Compiler.BurnUXContainerId != container.Id && 0 < container.Payloads.Count)
                    {
                        writer.WriteStartElement("Container");
                        WriteBurnManifestContainerAttributes(writer, executableName, container, attachedContainerIndex, this.FileManager);
                        writer.WriteEndElement();
                        if ("attached" == container.Type)
                        {
                            attachedContainerIndex++;
                        }
                    }
                }

                foreach (PayloadInfoRow payload in allPayloads.Values)
                {
                    if (PackagingType.Embedded == payload.Packaging && Compiler.BurnUXContainerId != payload.Container)
                    {
                        writer.WriteStartElement("Payload");
                        WriteBurnManifestPayloadAttributes(writer, payload, true, this.FileManager, allPayloads);
                        writer.WriteEndElement();
                    }
                    else if (PackagingType.External == payload.Packaging)
                    {
                        writer.WriteStartElement("Payload");
                        WriteBurnManifestPayloadAttributes(writer, payload, false, this.FileManager, allPayloads);
                        writer.WriteEndElement();
                    }
                }

                foreach (RollbackBoundaryInfo rollbackBoundary in chain.RollbackBoundaries)
                {
                    writer.WriteStartElement("RollbackBoundary");
                    writer.WriteAttributeString("Id", rollbackBoundary.Id);
                    writer.WriteAttributeString("Vital", YesNoType.Yes == rollbackBoundary.Vital ? "yes" : "no");
                    writer.WriteEndElement();
                }

                // Write the registration information...
                writer.WriteStartElement("Registration");

                writer.WriteAttributeString("Id", bundleInfo.BundleId.ToString("B"));
                writer.WriteAttributeString("ExecutableName", executableName);
                writer.WriteAttributeString("PerMachine", bundleInfo.PerMachine ? "yes" : "no");
                writer.WriteAttributeString("Tag", bundleInfo.Tag);
                writer.WriteAttributeString("Version", bundleInfo.Version);
                writer.WriteAttributeString("ProviderKey", bundleInfo.ProviderKey);

                writer.WriteStartElement("Arp");
                writer.WriteAttributeString("Register", (0 < bundleInfo.DisableModify && bundleInfo.DisableRemove) ? "no" : "yes"); // do not register if disabled modify and remove.
                writer.WriteAttributeString("DisplayName", bundleInfo.Name);
                writer.WriteAttributeString("DisplayVersion", bundleInfo.Version);

                if (!String.IsNullOrEmpty(bundleInfo.Publisher))
                {
                    writer.WriteAttributeString("Publisher", bundleInfo.Publisher);
                }

                if (!String.IsNullOrEmpty(bundleInfo.HelpLink))
                {
                    writer.WriteAttributeString("HelpLink", bundleInfo.HelpLink);
                }

                if (!String.IsNullOrEmpty(bundleInfo.HelpTelephone))
                {
                    writer.WriteAttributeString("HelpTelephone", bundleInfo.HelpTelephone);
                }

                if (!String.IsNullOrEmpty(bundleInfo.AboutUrl))
                {
                    writer.WriteAttributeString("AboutUrl", bundleInfo.AboutUrl);
                }

                if (!String.IsNullOrEmpty(bundleInfo.UpdateUrl))
                {
                    writer.WriteAttributeString("UpdateUrl", bundleInfo.UpdateUrl);
                }

                if (!String.IsNullOrEmpty(bundleInfo.ParentName))
                {
                    writer.WriteAttributeString("ParentDisplayName", bundleInfo.ParentName);
                }

                if (1 == bundleInfo.DisableModify)
                {
                    writer.WriteAttributeString("DisableModify", "yes");
                }
                else if (2 == bundleInfo.DisableModify)
                {
                    writer.WriteAttributeString("DisableModify", "button");
                }

                if (bundleInfo.DisableRemove)
                {
                    writer.WriteAttributeString("DisableRemove", "yes");
                }
                writer.WriteEndElement(); // </Arp>

                if (null != updateRegistrationInfo)
                {
                    writer.WriteStartElement("Update"); // <Update>
                    writer.WriteAttributeString("Manufacturer", updateRegistrationInfo.Manufacturer);

                    if (!String.IsNullOrEmpty(updateRegistrationInfo.Department))
                    {
                        writer.WriteAttributeString("Department", updateRegistrationInfo.Department);
                    }

                    if (!String.IsNullOrEmpty(updateRegistrationInfo.ProductFamily))
                    {
                        writer.WriteAttributeString("ProductFamily", updateRegistrationInfo.ProductFamily);
                    }

                    writer.WriteAttributeString("Name", updateRegistrationInfo.Name);
                    writer.WriteAttributeString("Classification", updateRegistrationInfo.Classification);
                    writer.WriteEndElement(); // </Update>
                }

                if (null != wixBundleTagTable)
                {
                    foreach (Row row in wixBundleTagTable.Rows)
                    {
                        writer.WriteStartElement("SoftwareTag");
                        writer.WriteAttributeString("Filename", (string)row[0]);
                        writer.WriteAttributeString("Regid", (string)row[1]);
                        writer.WriteAttributeString("Path", (string)row[3]);
                        writer.WriteCData((string)row[5]);
                        writer.WriteEndElement();
                    }
                }

                writer.WriteEndElement(); // </Register>

                // write the Chain...
                writer.WriteStartElement("Chain");
                if (chain.DisableRollback)
                {
                    writer.WriteAttributeString("DisableRollback", "yes");
                }

                if (chain.DisableSystemRestore)
                {
                    writer.WriteAttributeString("DisableSystemRestore", "yes");
                }

                if (chain.ParallelCache)
                {
                    writer.WriteAttributeString("ParallelCache", "yes");
                }

                // Build up the list of target codes from all the MSPs in the chain.
                List<WixBundlePatchTargetCodeRow> targetCodes = new List<WixBundlePatchTargetCodeRow>();

                foreach (ChainPackageInfo package in chain.Packages)
                {
                    writer.WriteStartElement(String.Format(CultureInfo.InvariantCulture, "{0}Package", package.ChainPackageType));

                    writer.WriteAttributeString("Id", package.Id);

                    switch (package.Cache)
                    {
                        case YesNoAlwaysType.No:
                            writer.WriteAttributeString("Cache", "no");
                            break;
                        case YesNoAlwaysType.Yes:
                            writer.WriteAttributeString("Cache", "yes");
                            break;
                        case YesNoAlwaysType.Always:
                            writer.WriteAttributeString("Cache", "always");
                            break;
                    }

                    writer.WriteAttributeString("CacheId", package.CacheId);
                    writer.WriteAttributeString("InstallSize", Convert.ToString(package.InstallSize));
                    writer.WriteAttributeString("Size", Convert.ToString(package.Size));
                    writer.WriteAttributeString("PerMachine", YesNoDefaultType.Yes == package.PerMachine ? "yes" : "no");
                    writer.WriteAttributeString("Permanent", package.Permanent ? "yes" : "no");
                    writer.WriteAttributeString("Vital", package.Vital ? "yes" : "no");

                    if (null != package.RollbackBoundary)
                    {
                        writer.WriteAttributeString("RollbackBoundaryForward", package.RollbackBoundary.Id);
                    }

                    if (!String.IsNullOrEmpty(package.RollbackBoundaryBackwardId))
                    {
                        writer.WriteAttributeString("RollbackBoundaryBackward", package.RollbackBoundaryBackwardId);
                    }

                    if (!String.IsNullOrEmpty(package.LogPathVariable))
                    {
                        writer.WriteAttributeString("LogPathVariable", package.LogPathVariable);
                    }

                    if (!String.IsNullOrEmpty(package.RollbackLogPathVariable))
                    {
                        writer.WriteAttributeString("RollbackLogPathVariable", package.RollbackLogPathVariable);
                    }

                    if (!String.IsNullOrEmpty(package.InstallCondition))
                    {
                        writer.WriteAttributeString("InstallCondition", package.InstallCondition);
                    }

                    if (Compiler.ChainPackageType.Exe == package.ChainPackageType)
                    {
                        writer.WriteAttributeString("DetectCondition", package.DetectCondition);
                        writer.WriteAttributeString("InstallArguments", package.InstallCommand);
                        writer.WriteAttributeString("UninstallArguments", package.UninstallCommand);
                        writer.WriteAttributeString("RepairArguments", package.RepairCommand);
                        writer.WriteAttributeString("Repairable", package.Repairable ? "yes" : "no");
                        if (!String.IsNullOrEmpty(package.Protocol))
                        {
                            writer.WriteAttributeString("Protocol", package.Protocol);
                        }
                    }
                    else if (Compiler.ChainPackageType.Msi == package.ChainPackageType)
                    {
                        writer.WriteAttributeString("ProductCode", package.ProductCode);
                        writer.WriteAttributeString("Language", package.Language);
                        writer.WriteAttributeString("Version", package.Version);
                        writer.WriteAttributeString("DisplayInternalUI", package.DisplayInternalUI ? "yes" : "no");
                    }
                    else if (Compiler.ChainPackageType.Msp == package.ChainPackageType)
                    {
                        writer.WriteAttributeString("PatchCode", package.PatchCode);
                        writer.WriteAttributeString("PatchXml", package.PatchXml);
                        writer.WriteAttributeString("DisplayInternalUI", package.DisplayInternalUI ? "yes" : "no");

                        // If there is still a chance that all of our patches will target a narrow set of
                        // product codes, add the patch list to the overall list.
                        if (null != targetCodes)
                        {
                            if (!package.TargetUnspecified)
                            {
                                targetCodes.AddRange(package.TargetCodes);
                            }
                            else // we have a patch that targets the world, so throw the whole list away.
                            {
                                targetCodes = null;
                            }
                        }
                    }
                    else if (Compiler.ChainPackageType.Msu == package.ChainPackageType)
                    {
                        writer.WriteAttributeString("DetectCondition", package.DetectCondition);
                        writer.WriteAttributeString("KB", package.MsuKB);
                    }

                    foreach (MsiFeature feature in package.MsiFeatures)
                    {
                        writer.WriteStartElement("MsiFeature");
                        writer.WriteAttributeString("Id", feature.Name);
                        writer.WriteEndElement();
                    }

                    foreach (MsiPropertyInfo msiProperty in package.MsiProperties)
                    {
                        writer.WriteStartElement("MsiProperty");
                        writer.WriteAttributeString("Id", msiProperty.Name);
                        writer.WriteAttributeString("Value", msiProperty.Value);
                        writer.WriteEndElement();
                    }

                    foreach (string slipstreamMsp in package.SlipstreamMsps)
                    {
                        writer.WriteStartElement("SlipstreamMsp");
                        writer.WriteAttributeString("Id", slipstreamMsp);
                        writer.WriteEndElement();
                    }

                    foreach (ExitCodeInfo exitCode in package.ExitCodes)
                    {
                        writer.WriteStartElement("ExitCode");
                        writer.WriteAttributeString("Type", exitCode.Type);
                        writer.WriteAttributeString("Code", exitCode.Code);
                        writer.WriteEndElement();
                    }

                    if (commandLinesByPackage.ContainsKey(package.Id))
                    {
                        foreach (WixCommandLineRow commandLine in commandLinesByPackage[package.Id])
                        {
                            writer.WriteStartElement("CommandLine");
                            writer.WriteAttributeString("InstallArgument", commandLine.InstallArgument);
                            writer.WriteAttributeString("UninstallArgument", commandLine.UninstallArgument);
                            writer.WriteAttributeString("RepairArgument", commandLine.RepairArgument);
                            writer.WriteAttributeString("Condition", commandLine.Condition);
                            writer.WriteEndElement();
                        }
                    }

                    // Output the dependency information.
                    foreach (ProvidesDependency dependency in package.Provides)
                    {
                        // TODO: Add to wixpdb as an imported table, or link package wixpdbs to bundle wixpdbs.
                        dependency.WriteXml(writer);
                    }

                    foreach (RelatedPackage related in package.RelatedPackages)
                    {
                        writer.WriteStartElement("RelatedPackage");
                        writer.WriteAttributeString("Id", related.Id);
                        if (!String.IsNullOrEmpty(related.MinVersion))
                        {
                            writer.WriteAttributeString("MinVersion", related.MinVersion);
                            writer.WriteAttributeString("MinInclusive", related.MinInclusive ? "yes" : "no");
                        }
                        if (!String.IsNullOrEmpty(related.MaxVersion))
                        {
                            writer.WriteAttributeString("MaxVersion", related.MaxVersion);
                            writer.WriteAttributeString("MaxInclusive", related.MaxInclusive ? "yes" : "no");
                        }
                        writer.WriteAttributeString("OnlyDetect", related.OnlyDetect ? "yes" : "no");
                        if (0 < related.Languages.Count)
                        {
                            writer.WriteAttributeString("LangInclusive", related.LangInclusive ? "yes" : "no");
                            foreach (string language in related.Languages)
                            {
                                writer.WriteStartElement("Language");
                                writer.WriteAttributeString("Id", language);
                                writer.WriteEndElement();
                            }
                        }
                        writer.WriteEndElement();
                    }

                    // Write any contained Payloads with the PackagePayload being first
                    writer.WriteStartElement("PayloadRef");
                    writer.WriteAttributeString("Id", package.PackagePayload.Id);
                    writer.WriteEndElement();

                    foreach (PayloadInfoRow payload in package.Payloads)
                    {
                        if (payload.Id != package.PackagePayload.Id)
                        {
                            writer.WriteStartElement("PayloadRef");
                            writer.WriteAttributeString("Id", payload.Id);
                            writer.WriteEndElement();
                        }
                    }

                    writer.WriteEndElement(); // </XxxPackage>
                }
                writer.WriteEndElement(); // </Chain>

                if (null != targetCodes)
                {
                    foreach (WixBundlePatchTargetCodeRow targetCode in targetCodes)
                    {
                        writer.WriteStartElement("PatchTargetCode");
                        writer.WriteAttributeString("TargetCode", targetCode.TargetCode);
                        writer.WriteAttributeString("Product", targetCode.TargetsProductCode ? "yes" : "no");
                        writer.WriteEndElement();
                    }
                }

                // write the ApprovedExeForElevation elements
                if (0 < approvedExesForElevation.Count)
                {
                    foreach (ApprovedExeForElevation approvedExeForElevation in approvedExesForElevation)
                    {
                        writer.WriteStartElement("ApprovedExeForElevation");
                        writer.WriteAttributeString("Id", approvedExeForElevation.Id);
                        writer.WriteAttributeString("Key", approvedExeForElevation.Key);

                        if (!String.IsNullOrEmpty(approvedExeForElevation.ValueName))
                        {
                            writer.WriteAttributeString("ValueName", approvedExeForElevation.ValueName);
                        }

                        if (approvedExeForElevation.Win64)
                        {
                            writer.WriteAttributeString("Win64", "yes");
                        }

                        writer.WriteEndElement();
                    }
                }

                writer.WriteEndDocument(); // </BurnManifest>
            }
        }