From 70b1f5c5e5f3bfe848013e61c9117bb6a01b0d59 Mon Sep 17 00:00:00 2001 From: Rob Lenders <138088099+rob-oehm-automation@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:21:47 -0500 Subject: [PATCH] Add functionality to pack and retrieve arbitrary files --- .../XmlSchemas/ExcelDna.DnaLibrary.xsd | 21 ++++++++++ Source/ExcelDna.Integration/DnaLibrary.cs | 42 +++++++++++++++++++ Source/ExcelDna.Integration/Excel.cs | 19 +++++++++ .../ExcelDna.Integration/ExcelIntegration.cs | 5 +++ .../ExcelDna.Integration/IIntegrationHost.cs | 2 +- Source/ExcelDna.Integration/Reference.cs | 20 ++++++++- .../ExcelDna.PackedResources/ExcelDnaPack.cs | 25 +++++++++++ .../ResourceHelper.cs | 1 + 8 files changed, 133 insertions(+), 2 deletions(-) diff --git a/Distribution/XmlSchemas/ExcelDna.DnaLibrary.xsd b/Distribution/XmlSchemas/ExcelDna.DnaLibrary.xsd index e0f49645..1df66c66 100644 --- a/Distribution/XmlSchemas/ExcelDna.DnaLibrary.xsd +++ b/Distribution/XmlSchemas/ExcelDna.DnaLibrary.xsd @@ -206,6 +206,22 @@ + + + + + + + + + + + + Images set { _Images = value; } } + private List _Files; + [XmlElement("File", typeof(DnaFile))] + public List Files + { + get { return _Files; } + set { _Files = value; } + } + private string dnaResolveRoot; // Get projects explicit and implicitly present in the library @@ -726,6 +734,40 @@ public Bitmap GetImage(string imageId) return null; } + public byte[] GetFileBytes(string fileId) + { + // TODO: Consider if this should be a Stream instead of a byte[] + // This would allow for larger files to be handled more efficiently. + + // First check if fileId is in the DnaLibrary's File list. + // DOCUMENT: Case sensitive match. + foreach (DnaFile file in Files) + { + if (file.Name == fileId && file.Path != null) + { + byte[] fileBytes; + if (file.Path.StartsWith("packed:")) + { + string resourceName = file.Path.Substring(7); + fileBytes = ExcelIntegration.GetFileBytes(resourceName); + } + else + { + string filePath = ResolvePath(file.Path); + if (filePath == null) + { + // This is the file but we could not find it !? + Logger.Initialization.Warn("DnaLibrary.GetFile - For file {0} the path resolution failed: {1}", file.Name, file.Path); + return null; + } + fileBytes = File.ReadAllBytes(filePath); + } + return fileBytes; + } + } + return null; + } + } //public class CustomUI : IXmlSerializable diff --git a/Source/ExcelDna.Integration/Excel.cs b/Source/ExcelDna.Integration/Excel.cs index 6a9ab7c8..c775e1fc 100644 --- a/Source/ExcelDna.Integration/Excel.cs +++ b/Source/ExcelDna.Integration/Excel.cs @@ -11,6 +11,8 @@ using System.IO; using System.Reflection; using System.Runtime.ExceptionServices; +using System.Collections.Generic; +using System.Linq; namespace ExcelDna.Integration { @@ -782,6 +784,23 @@ public static bool SupportsDynamicArrays } } #endregion + + #region Packed Files + /// Returns the names of all the resources packed in the XLL. + /// An enumerable that contains the names of all the resources. + public static IEnumerable GetPackedFileNames() + { + return DnaLibrary.CurrentLibrary.Files.Select(f => f.Name); + } + + /// Loads the specified resource from the XLL. + /// The case-sensitive name of the resource being requested. + /// The resource; or if the resource does not exist in the XLL. + public static byte[] GetPackedFileBytes(string name) + { + return DnaLibrary.CurrentLibrary.GetFileBytes(name); + } + #endregion } public class ExcelLimits diff --git a/Source/ExcelDna.Integration/ExcelIntegration.cs b/Source/ExcelDna.Integration/ExcelIntegration.cs index ba97364b..7ec8a374 100644 --- a/Source/ExcelDna.Integration/ExcelIntegration.cs +++ b/Source/ExcelDna.Integration/ExcelIntegration.cs @@ -183,6 +183,11 @@ internal static byte[] GetImageBytes(string imageName) return _integrationHost.GetResourceBytes(imageName, 2); } + internal static byte[] GetFileBytes(string fileName) + { + return _integrationHost.GetResourceBytes(fileName, 2); + } + internal static byte[] GetSourceBytes(string sourceName) { return _integrationHost.GetResourceBytes(sourceName, 3); diff --git a/Source/ExcelDna.Integration/IIntegrationHost.cs b/Source/ExcelDna.Integration/IIntegrationHost.cs index 8eb5fe09..ea421363 100644 --- a/Source/ExcelDna.Integration/IIntegrationHost.cs +++ b/Source/ExcelDna.Integration/IIntegrationHost.cs @@ -8,7 +8,7 @@ namespace ExcelDna.Integration interface IIntegrationHost { XlCall.XlReturn TryExcelImpl(int xlFunction, out object result, params object[] parameters); - byte[] GetResourceBytes(string resourceName, int type); // types: 0 - Assembly, 1 - Dna file, 2 - Image + byte[] GetResourceBytes(string resourceName, int type); // types: 0 - Assembly, 1 - Dna file, 2 - Image or File, 3 - Source, 4 - PDB Assembly LoadFromAssemblyPath(string assemblyPath); Assembly LoadFromAssemblyBytes(byte[] assemblyBytes, byte[] pdbBytes); void RegisterMethods(List methods); diff --git a/Source/ExcelDna.Integration/Reference.cs b/Source/ExcelDna.Integration/Reference.cs index 688c2409..672f6fa0 100644 --- a/Source/ExcelDna.Integration/Reference.cs +++ b/Source/ExcelDna.Integration/Reference.cs @@ -53,7 +53,7 @@ public Reference(string path) { Path = path; } - } + } [Serializable] [XmlType(AnonymousType = true)] @@ -73,4 +73,22 @@ public Image() } } + [Serializable] + [XmlType(AnonymousType = true)] + public class DnaFile + { + [XmlAttribute] + public string Name; + + [XmlAttribute] + public string Path; + + [XmlAttribute] + public bool Pack; + + public DnaFile() + { + } + } + } diff --git a/Source/ExcelDna.PackedResources/ExcelDnaPack.cs b/Source/ExcelDna.PackedResources/ExcelDnaPack.cs index 012f1a33..72a4aa9d 100644 --- a/Source/ExcelDna.PackedResources/ExcelDnaPack.cs +++ b/Source/ExcelDna.PackedResources/ExcelDnaPack.cs @@ -402,6 +402,31 @@ static private byte[] PackDnaLibrary(string dnaPath, byte[] dnaContent, string d } } } + foreach (DnaFile file in dna.Files) + { + if (file.Pack) + { + string path = dna.ResolvePath(file.Path); + if (path == null) + { + var format = " ~~> ERROR: File path {0} NOT RESOLVED."; + errorMessage = string.Format(format, file.Path); + buildLogger.Error(typeof(ExcelDnaPack), format, file.Path); + throw new InvalidOperationException(errorMessage); + } + if (filesToPublish == null) + { + string name = Path.GetFileNameWithoutExtension(path).ToUpperInvariant() + "_" + lastPackIndex++ + Path.GetExtension(path).ToUpperInvariant(); + byte[] fileBytes = File.ReadAllBytes(path); + ru.AddFile(fileBytes, name, ResourceHelper.TypeName.FILE, null, compress, multithreading); + file.Path = "packed:" + name; + } + else + { + filesToPublish.Add(path); + } + } + } foreach (Project project in dna.Projects) { foreach (SourceItem source in project.SourceItems) diff --git a/Source/ExcelDna.PackedResources/ResourceHelper.cs b/Source/ExcelDna.PackedResources/ResourceHelper.cs index d79fa113..a32e617e 100644 --- a/Source/ExcelDna.PackedResources/ResourceHelper.cs +++ b/Source/ExcelDna.PackedResources/ResourceHelper.cs @@ -25,6 +25,7 @@ internal enum TypeName SOURCE = 3, PDB = 4, NATIVE_LIBRARY = 5, + FILE = 6, } // TODO: Learn about locales