/// <summary>
        /// Exports the specified updates from a local update metadata source to a format compatible with WSUS 2016
        /// </summary>
        /// <param name="updatesToExport">The updates to export. All categories from the source are also exported</param>
        /// <param name="exportFilePath">The export destination file (CAB)</param>
        public void Export(List <Update> updatesToExport, string exportFilePath)
        {
            var exportDirectory = Directory.GetParent(exportFilePath);

            if (!exportDirectory.Exists)
            {
                Directory.CreateDirectory(exportDirectory.FullName);
            }

            // Pack all XML blobs for updates to be exported into a flat text file
            var progress = new OperationProgress()
            {
                CurrentOperation = OperationType.ExportUpdateXmlBlobStart
            };

            ExportProgress?.Invoke(this, progress);

            var metadataFile = Path.Combine(exportDirectory.FullName, "metadata.txt");

            WriteMetadataFile(updatesToExport, metadataFile);

            progress.CurrentOperation = OperationType.ExportUpdateXmlBlobEnd;
            ExportProgress?.Invoke(this, progress);

            // Write metadata for all exported updates, languages and files
            progress.CurrentOperation = OperationType.ExportMetadataStart;
            ExportProgress?.Invoke(this, progress);

            var packageXmlFile = Path.Combine(exportDirectory.FullName, "package.xml");

            WritePackagesXml(updatesToExport, packageXmlFile);

            progress.CurrentOperation = OperationType.ExportMetadataEnd;
            ExportProgress?.Invoke(this, progress);

            // Add the above 2 files to a CAB archive
            progress.CurrentOperation = OperationType.CompressExportFileStart;
            ExportProgress?.Invoke(this, progress);

            var result = CabinetUtility.CompressFiles(new List <string>()
            {
                metadataFile, packageXmlFile
            }, exportFilePath);

            progress.CurrentOperation = OperationType.CompressExportFileEnd;
            ExportProgress?.Invoke(this, progress);

            // Delete temporary files
            if (File.Exists(metadataFile))
            {
                File.Delete(metadataFile);
            }

            if (File.Exists(packageXmlFile))
            {
                File.Delete(packageXmlFile);
            }
        }
Example #2
0
        /// <summary>
        /// Adds a list of updates to the query result. The XML metadata is written to disk to avoid running out of memory
        /// </summary>
        /// <param name="overTheWireUpdates">The updates to add to the result</param>
        public void AddUpdates(IEnumerable <ServerSyncUpdateData> overTheWireUpdates)
        {
            foreach (var overTheWireUpdate in overTheWireUpdates)
            {
                var updateIdentity = new Identity(overTheWireUpdate.Id);

                bool newEntryToBeAdded = false;
                lock (Identities)
                {
                    if (!Identities.Contains(updateIdentity))
                    {
                        newEntryToBeAdded = true;
                    }
                }

                if (newEntryToBeAdded)
                {
                    // We need to parse the XML update blob
                    string updateXml = overTheWireUpdate.XmlUpdateBlob;
                    if (string.IsNullOrEmpty(updateXml))
                    {
                        // If the plain text blob is not availabe, use the compressed XML blob
                        if (overTheWireUpdate.XmlUpdateBlobCompressed == null || overTheWireUpdate.XmlUpdateBlobCompressed.Length == 0)
                        {
                            throw new Exception("Missing XmlUpdateBlobCompressed");
                        }

                        // Note: This only works on Windows.
                        updateXml = CabinetUtility.DecompressData(overTheWireUpdate.XmlUpdateBlobCompressed);
                    }

                    var xdoc      = XDocument.Parse(updateXml, LoadOptions.None);
                    var newUpdate = Update.FromUpdateXml(updateIdentity, xdoc);
                    AddUpdate(newUpdate, updateXml, out var newUpdateIndex, xdoc);
                }
            }
        }