/// <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); } }
/// <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); } } }