// Returns the resulting source for this SourceItem. // If Path is filled in, and file exists, takes source from there. // Else returns Code value. public string GetSource(string pathResolveRoot) { if (!string.IsNullOrEmpty(Path)) { if (Path.StartsWith("packed:")) { string resourceName = Path.Substring(7); byte[] sourceBytes = ExcelIntegration.GetSourceBytes(resourceName); return(Encoding.UTF8.GetString(sourceBytes)); } else { // Try to read from a file. string resolvedPath = DnaLibrary.ResolvePath(Path, pathResolveRoot); if (resolvedPath == null) { Debug.Print("Source path {0} could not be resolved.", Path); } else { return(File.ReadAllText(resolvedPath).Trim()); } } } return(Code); }
internal static void Initialize() { // Might be called more than once in a session // e.g. if AddInManagerInfo is called, and then AutoOpen // or if the add-in is opened more than once. // Load the current library // Get the .xll filename string xllDirectory = Path.GetDirectoryName(XllPath); string xllFileRoot = Path.GetFileNameWithoutExtension(XllPath); string dnaFileName = Path.Combine(xllDirectory, xllFileRoot + ".dna"); if (File.Exists(dnaFileName)) { currentLibrary = LoadFrom(dnaFileName); } else { // TODO: Load a default library as from .dll or from resources. ExcelDna.Logging.LogDisplay.SetText(string.Format("The required .dna script file {0} does not exist.", dnaFileName)); } // If there have been problems, ensure that there is at lease some current library. if (currentLibrary == null) { currentLibrary = new DnaLibrary(); } }
internal ExportedAssembly(Assembly assembly, bool explicitExports, bool comServer, bool isDynamic, string typeLibPath, DnaLibrary parentDnaLibrary) { this.Assembly = assembly; this.ExplicitExports = explicitExports; this.ComServer = comServer; this.IsDynamic = isDynamic; this.TypeLibPath = typeLibPath; this.ParentDnaLibrary = parentDnaLibrary; }
public static void Save(string fileName, DnaLibrary dnaLibrary) { // XmlSerializer serializer = new XmlSerializer(typeof(DnaLibrary)); XmlSerializer serializer = new DnaLibrarySerializer(); using (FileStream fileStream = new FileStream(fileName, FileMode.Truncate)) { serializer.Serialize(fileStream, dnaLibrary); } }
internal static void Save(string fileName, DnaLibrary dnaProject) { // XmlSerializer serializer = new XmlSerializer(typeof(DnaLibrary)); XmlSerializer serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.DnaLibrarySerializer(); using (FileStream fileStream = new FileStream(fileName, FileMode.Truncate)) { serializer.Serialize(fileStream, dnaProject); } }
public List <Assembly> GetAssemblies() { try { string realPath = Path; if (!File.Exists(realPath)) { string xllName = DnaLibrary.XllPath; string localDirectory = System.IO.Path.GetDirectoryName(xllName); if (System.IO.Path.IsPathRooted(realPath)) { // Rooted path -- try locally string fileName = System.IO.Path.GetFileName(realPath); realPath = System.IO.Path.Combine(localDirectory, fileName); } else { // Try a path relative to local directory realPath = System.IO.Path.Combine(localDirectory, realPath); } // Check again if (!File.Exists(realPath)) { // Give up. Debug.Print("Could not find file " + Path); return(new List <Assembly>()); } } if (System.IO.Path.GetExtension(realPath).ToLower() == ".dna") { // Load as a DnaLibrary DnaLibrary lib = DnaLibrary.LoadFrom(realPath); if (lib == null) { // Problems during load. return(new List <Assembly>()); } return(lib.GetAssemblies()); } else { // Load as a regular assembly List <Assembly> list = new List <Assembly>(); list.Add(Assembly.LoadFrom(realPath)); return(list); } } catch (Exception e) { // Assembly could not be loaded. Debug.Print("Assembly load exception for file: " + Path + "\n" + e.ToString()); return(new List <Assembly>()); } }
public static byte[] Save(DnaLibrary dnaLibrary) { // XmlSerializer serializer = new XmlSerializer(typeof(DnaLibrary)); XmlSerializer serializer = new DnaLibrarySerializer(); using (MemoryStream ms = new MemoryStream()) { serializer.Serialize(ms, dnaLibrary); return(ms.ToArray()); } }
internal static void InitializeRootLibrary(string xllPath) { // Loads the primary .dna library // Load sequence is: // 1. Look for a packed .dna file named "__MAIN__" in the .xll. // 2. Look for the .dna file in the same directory as the .xll file, with the same name and extension .dna. // CAREFUL: Sequence here is fragile - this is the first place where we start logging _XllPath = xllPath; _xllPathPathInfo = new FileInfo(xllPath); Logging.LogDisplay.CreateInstance(); Logger.Initialization.Verbose("Enter DnaLibrary.InitializeRootLibrary"); byte[] dnaBytes = ExcelIntegration.GetDnaFileBytes("__MAIN__"); if (dnaBytes != null) { Logger.Initialization.Verbose("Got Dna file from resources."); string pathResolveRoot = Path.GetDirectoryName(DnaLibrary.XllPath); rootLibrary = LoadFrom(dnaBytes, pathResolveRoot); // ... would have displayed error and returned null if there was an error. } else { Logger.Initialization.Verbose("No Dna file in resources - looking for file."); // No packed .dna file found - load from a .dna file. string dnaFileName = Path.ChangeExtension(XllPath, ".dna"); rootLibrary = LoadFrom(dnaFileName); // ... would have displayed error and returned null if there was an error. } // If there have been problems, ensure that there is at lease some current library. if (rootLibrary == null) { Logger.Initialization.Error("No Dna Library found."); rootLibrary = new DnaLibrary(); } rootLibrary.Initialize(); Logger.Initialization.Verbose("Exit DnaLibrary.Initialize"); }
public static byte[] Save(DnaLibrary dnaLibrary) { // XmlSerializer serializer = new XmlSerializer(typeof(DnaLibrary)); XmlSerializer serializer = new DnaLibrarySerializer(); using (MemoryStream ms = new MemoryStream()) { serializer.Serialize(ms, dnaLibrary); return ms.ToArray(); } }
internal static void DeInitialize() { // Called to shut down the Add-In. // Free whatever possible rootLibrary = null; }
internal static void InitializeRootLibrary(string xllPath) { // Loads the primary .dna library // Load sequence is: // 1. Look for a packed .dna file named "__MAIN__" in the .xll. // 2. Look for the .dna file in the same directory as the .xll file, with the same name and extension .dna. // CAREFUL: Sequence here is fragile - this is the first place where we start logging _XllPath = xllPath; Logging.LogDisplay.CreateInstance(); Logger.Initialization.Verbose("Enter DnaLibrary.InitializeRootLibrary"); byte[] dnaBytes = ExcelIntegration.GetDnaFileBytes("__MAIN__"); if (dnaBytes != null) { Logger.Initialization.Verbose("Got Dna file from resources."); string pathResolveRoot = Path.GetDirectoryName(DnaLibrary.XllPath); rootLibrary = LoadFrom(dnaBytes, pathResolveRoot); // ... would have displayed error and returned null if there was an error. } else { Logger.Initialization.Verbose("No Dna file in resources - looking for file."); // No packed .dna file found - load from a .dna file. string dnaFileName = Path.ChangeExtension(XllPath, ".dna"); rootLibrary = LoadFrom(dnaFileName); // ... would have displayed error and returned null if there was an error. } // If there have been problems, ensure that there is at lease some current library. if (rootLibrary == null) { Logger.Initialization.Error("No Dna Library found."); rootLibrary = new DnaLibrary(); } rootLibrary.Initialize(); Logger.Initialization.Verbose("Exit DnaLibrary.Initialize"); }
// TODO: Move compilation stuff elsewhere. // TODO: Consider IronPython support: http://www.ironpython.info/index.php/Using_Compiled_Python_Classes_from_.NET/CSharp_IP_2.6 internal List<ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary) { List<ExportedAssembly> list = new List<ExportedAssembly>(); // Dynamically compile this project to an in-memory assembly CodeDomProvider provider = GetProvider(); if (provider == null) return list; CompilerParameters cp = new CompilerParameters(); // TODO: Debug build ? // cp.IncludeDebugInformation = true; cp.GenerateExecutable = false; //cp.OutputAssembly = Name; // TODO: Keep track of built assembly for the project cp.GenerateInMemory = true; cp.TreatWarningsAsErrors = false; // This is attempt to fix the bug reported on the group, where the add-in compilation fails if the add-in is put into c:\ // It is caused by a quirk of the 'Path.GetDirectoryName' function when dealing with the path "c:\test.abc" // - it leaves the last DirectorySeparator in the path in this special case. // Thanks to Nemo for the great fix. //local variable to hold the quoted/unquoted version of the executing dirction string ProcessedExecutingDirectory = DnaLibrary.ExecutingDirectory; if (ProcessedExecutingDirectory.IndexOf(' ') != -1) ProcessedExecutingDirectory = "\"" + ProcessedExecutingDirectory + "\""; //set compiler command line vars as needed if (provider is Microsoft.VisualBasic.VBCodeProvider) { cp.CompilerOptions = " /libPath:" + ProcessedExecutingDirectory; if (DefaultImports) { string importsList = "Microsoft.VisualBasic,System,System.Collections,System.Collections.Generic,System.Data,System.Diagnostics,ExcelDna.Integration"; if (Environment.Version.Major >= 4) { importsList += ",System.Linq,System.Xml.Linq"; } cp.CompilerOptions += " /imports:" + importsList; } } else if (provider is Microsoft.CSharp.CSharpCodeProvider) { cp.CompilerOptions = " /lib:" + ProcessedExecutingDirectory; } else if (provider.GetType().FullName.ToLower().IndexOf(".jscript.") != -1) { cp.CompilerOptions = " /lib:" + ProcessedExecutingDirectory; } else if (provider.GetType().FullName == "Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider") { cp.CompilerOptions = " --nologo -I " + ProcessedExecutingDirectory; // In F# 2.0, the --nologo is redundant - I leave it because it does no harm. // FSharp 2.0 compiler will target .NET 4 unless we do something to ensure .NET 2.0. // It seems adding an explicit reference to the .NET 2.0 version of mscorlib.dll is good enough. if (Environment.Version.Major < 4) { // Explicitly add a reference to the mscorlib version from the currently running .NET version string libPath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "mscorlib.dll"); cp.ReferencedAssemblies.Add(libPath); } } // TODO: Consider what to do if we can't resolve some of the Reference paths -- do we try to compile anyway, throw an exception, ...what? List<string> refPaths = GetReferencePaths(pathResolveRoot, provider); cp.ReferencedAssemblies.AddRange(refPaths.ToArray()); List<string> sources = GetSources(pathResolveRoot); CompilerResults cr = provider.CompileAssemblyFromSource(cp, sources.ToArray()); foreach (string path in tempAssemblyPaths) { File.Delete(path); } tempAssemblyPaths.Clear(); if (cr.Errors.HasErrors) { ExcelDna.Logging.LogDisplay.WriteLine("There were errors when compiling project: " + Name); foreach (CompilerError err in cr.Errors) { ExcelDna.Logging.LogDisplay.WriteLine(err.ToString()); } return list; } // Success !! // Now add all the references // TODO: How to remove again?? foreach (Reference r in References) { AssemblyReference.AddAssembly(r.Path); } // TODO: Create TypeLib for execution-time compiled assemblies. list.Add(new ExportedAssembly(cr.CompiledAssembly, ExplicitExports, ComServer, true, null, dnaLibrary)); return list; }
internal static void InitializeRootLibrary(string xllPath) { // Might be called more than once in a session // if the add-in is opened more than once. // Loads the primary .dna library // Load sequence is: // 1. Look for a packed .dna file named "__MAIN__" in the .xll. // 2. Look for the .dna file in the same directory as the .xll file, with the same name and extension .dna. Debug.WriteLine("Enter DnaLibrary.InitializeRootLibrary"); XllPath = xllPath; Logging.LogDisplay.CreateInstance(); byte[] dnaBytes = Integration.GetDnaFileBytes("__MAIN__"); if (dnaBytes != null) { Debug.WriteLine("Got Dna file from resources."); string pathResolveRoot = Path.GetDirectoryName(DnaLibrary.XllPath); rootLibrary = LoadFrom(dnaBytes, pathResolveRoot); // ... would have displayed error and returned null if there was an error. } else { Debug.WriteLine("No Dna file in resources - looking for file."); // No packed .dna file found - load from a .dna file. string dnaFileName = Path.ChangeExtension(XllPath, ".dna"); rootLibrary = LoadFrom(dnaFileName); // ... would have displayed error and returned null if there was an error. } // If there have been problems, ensure that there is at lease some current library. if (rootLibrary == null) { Debug.WriteLine("No Dna Library found."); rootLibrary = new DnaLibrary(); } rootLibrary.Initialize(); Debug.WriteLine("Exit DnaLibrary.Initialize"); }
internal static void Initialize() { // Might be called more than once in a session // e.g. if AddInManagerInfo is called, and then AutoOpen // or if the add-in is opened more than once. // Load the current library // Get the .xll filename string xllDirectory = Path.GetDirectoryName(XllPath); string xllFileRoot = Path.GetFileNameWithoutExtension(XllPath); string dnaFileName = Path.Combine(xllDirectory, xllFileRoot + ".dna"); if (File.Exists(dnaFileName)) { currentLibrary = LoadFrom(dnaFileName); } else { // TODO: Load a default library as from .dll or from resources. ExcelDna.Logging.LogDisplay.SetText(string.Format("The required .dna script file {0} does not exist.", dnaFileName)); } // If there have been problems, ensure that there is at lease some current library. if (currentLibrary == null) currentLibrary = new DnaLibrary(); }
// TODO: Move compilation stuff elsewhere. // TODO: Consider IronPython support: http://www.ironpython.info/index.php/Using_Compiled_Python_Classes_from_.NET/CSharp_IP_2.6 internal List <ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary) { List <ExportedAssembly> list = new List <ExportedAssembly>(); // Dynamically compile this project to an in-memory assembly CodeDomProvider provider = GetProvider(); if (provider == null) { return(list); } CompilerParameters cp = new CompilerParameters(); bool isFsharp = false; // TODO: Debug build ? // cp.IncludeDebugInformation = true; cp.GenerateExecutable = false; //cp.OutputAssembly = Name; // TODO: Keep track of built assembly for the project cp.GenerateInMemory = true; cp.TreatWarningsAsErrors = false; // This is attempt to fix the bug reported on the group, where the add-in compilation fails if the add-in is put into c:\ // It is caused by a quirk of the 'Path.GetDirectoryName' function when dealing with the path "c:\test.abc" // - it leaves the last DirectorySeparator in the path in this special case. // Thanks to Nemo for the great fix. //local variable to hold the quoted/unquoted version of the executing dirction string ProcessedExecutingDirectory = DnaLibrary.ExecutingDirectory; if (ProcessedExecutingDirectory.IndexOf(' ') != -1) { ProcessedExecutingDirectory = "\"" + ProcessedExecutingDirectory + "\""; } //set compiler command line vars as needed if (provider is Microsoft.VisualBasic.VBCodeProvider) { cp.CompilerOptions = " /libPath:" + ProcessedExecutingDirectory; if (DefaultImports) { string importsList = "Microsoft.VisualBasic,System,System.Collections,System.Collections.Generic,System.Data,System.Diagnostics,ExcelDna.Integration"; if (Environment.Version.Major >= 4) { importsList += ",System.Linq,System.Xml.Linq"; } cp.CompilerOptions += " /imports:" + importsList; } } else if (provider is Microsoft.CSharp.CSharpCodeProvider) { cp.CompilerOptions = " /lib:" + ProcessedExecutingDirectory; } else if (provider.GetType().FullName.ToLower().IndexOf(".jscript.") != -1) { cp.CompilerOptions = " /lib:" + ProcessedExecutingDirectory; } else if (provider.GetType().FullName == "Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider") { isFsharp = true; cp.CompilerOptions = " --nologo -I " + ProcessedExecutingDirectory; // In F# 2.0, the --nologo is redundant - I leave it because it does no harm. // FSharp 2.0 compiler will target .NET 4 unless we do something to ensure .NET 2.0. // It seems adding an explicit reference to the .NET 2.0 version of mscorlib.dll is good enough. if (Environment.Version.Major < 4) { // Explicitly add a reference to the mscorlib version from the currently running .NET version string libPath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "mscorlib.dll"); cp.ReferencedAssemblies.Add(libPath); } } // TODO: Consider what to do if we can't resolve some of the Reference paths -- do we try to compile anyway, throw an exception, ...what? List <string> refPaths = GetReferencePaths(pathResolveRoot, provider); cp.ReferencedAssemblies.AddRange(refPaths.ToArray()); List <string> sources = GetSources(pathResolveRoot); CompilerResults cr; try { cr = provider.CompileAssemblyFromSource(cp, sources.ToArray()); } catch (Win32Exception wex) { if (isFsharp) { Logger.DnaCompilation.Error("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):"); string fsBinPath = Environment.GetEnvironmentVariable("FSHARP_BIN"); string msg; if (fsBinPath == null) { msg = " Calling the F# compiler failed (\"" + wex.Message + "\").\r\n" + " Please check that the F# compiler is correctly installed.\r\n" + " This error can sometimes be fixed by creating an FSHARP_BIN environment variable.\r\n" + " Create an environment variable FSHARP_BIN with the full path to the directory containing \r\n" + " the F# compiler fsc.exe - for example \r\n" + " \"" + @"C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0\"""; } else { msg = " Calling the F# compiler failed (\"" + wex.Message + "\").\r\n" + " Please check that the F# compiler is correctly installed, and that the FSHARP_BIN environment variable is correct\r\n" + " (it currently points to " + fsBinPath + ")."; } Logger.DnaCompilation.Error(msg); return(list); } throw; } foreach (string path in tempAssemblyPaths) { File.Delete(path); } tempAssemblyPaths.Clear(); if (cr.Errors.HasErrors) { Logger.DnaCompilation.Error("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):"); Logger.DnaCompilation.Error("There were errors when compiling project: " + Name); foreach (CompilerError err in cr.Errors) { Logger.DnaCompilation.Error(" " + err.ToString()); } return(list); } // Success !! // Now add all the references // TODO: How to remove again?? foreach (Reference r in References) { AssemblyReference.AddAssembly(r.Path); } // TODO: Create TypeLib for execution-time compiled assemblies. list.Add(new ExportedAssembly(cr.CompiledAssembly, ExplicitExports, ExplicitRegistration, ComServer, true, null, dnaLibrary)); return(list); }
public List <string> GetReferencePaths(string pathResolveRoot, CodeDomProvider provider) { List <string> refPaths = new List <string>(); if (References != null) { foreach (Reference rf in References) { bool isResolved = false; if (rf.Path != null) { if (rf.Path.StartsWith("packed:")) { string assName = rf.Path.Substring(7); string assPath = Path.GetTempFileName(); tempAssemblyPaths.Add(assPath); File.WriteAllBytes(assPath, ExcelIntegration.GetAssemblyBytes(assName)); refPaths.Add(assPath); isResolved = true; } else { // Call ResolvePath - check relative to pathResolveRoot and in framework directory. string refPath = DnaLibrary.ResolvePath(rf.Path, pathResolveRoot); if (!string.IsNullOrEmpty(refPath)) { refPaths.Add(refPath); isResolved = true; } } } if (!isResolved && rf.Name != null) { // Try to resolve by Name #pragma warning disable 0618 Assembly refAssembly = Assembly.LoadWithPartialName(rf.Name); #pragma warning restore 0618 if (refAssembly != null) { if (!string.IsNullOrEmpty(refAssembly.Location)) { refPaths.Add(refAssembly.Location); isResolved = true; } } } if (!isResolved) { // Must have been loaded by us from the packing....? Logger.DnaCompilation.Error("Assembly resolve failure - Reference Name: {0}, Path: {1}", rf.Name, rf.Path); } } } if (DefaultReferences) { // CONSIDER: Should these be considered more carefully? I'm just putting in what the default templates in Visual Studio 2010 put in. refPaths.Add("System.dll"); refPaths.Add("System.Data.dll"); refPaths.Add("System.Xml.dll"); if (Environment.Version.Major >= 4) { refPaths.Add("System.Core.dll"); refPaths.Add("System.Data.DataSetExtensions.dll"); refPaths.Add("System.Xml.Linq.dll"); if (provider is Microsoft.CSharp.CSharpCodeProvider) { refPaths.Add("Microsoft.CSharp.dll"); } } } // DOCUMENT: Reference to the xll is always added // Sort out "ExcelDna.Integration.dll" copy which causes problems // TODO: URGENT: Revisit this... (don't know what to do yet - maybe full AssemblyName). string location = Assembly.GetExecutingAssembly().Location; if (location != "") { refPaths.Add(location); } else { string assPath = Path.GetTempFileName(); tempAssemblyPaths.Add(assPath); File.WriteAllBytes(assPath, ExcelIntegration.GetAssemblyBytes("EXCELDNA.INTEGRATION")); refPaths.Add(assPath); } Logger.DnaCompilation.Verbose("Compiler References: "); foreach (string rfPath in refPaths) { Logger.DnaCompilation.Verbose(" " + rfPath); } return(refPaths); }
internal List<ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary) { List<ExportedAssembly> list = new List<ExportedAssembly>(); try { string realPath = Path; if (Path.StartsWith("packed:")) { string resourceName = Path.Substring(7); if (Path.ToUpperInvariant().EndsWith(".DNA")) { byte[] dnaContent = Integration.GetDnaFileBytes(resourceName); DnaLibrary lib = DnaLibrary.LoadFrom(dnaContent, pathResolveRoot); if (lib == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: Packed DnaLibrary could not be loaded."); return list; } return lib.GetAssemblies(pathResolveRoot); } else { byte[] rawAssembly = Integration.GetAssemblyBytes(resourceName); // DOCUMENT: TypeLibPath which is a resource in a library is denoted as fileName.dll\4 // For packed assemblies, we set TypeLibPath="packed:2" string typeLibPath = null; if (!string.IsNullOrEmpty(TypeLibPath) && TypeLibPath.StartsWith("packed:")) { typeLibPath = DnaLibrary.XllPath + @"\" + TypeLibPath.Substring(7); } list.Add(new ExportedAssembly(Assembly.Load(rawAssembly), ExplicitExports, ComServer, false, typeLibPath, dnaLibrary)); return list; } } if (Uri.IsWellFormedUriString(Path, UriKind.Absolute)) { // Here is support for loading ExternalLibraries from http. Uri uri = new Uri(Path, UriKind.Absolute); if (uri.IsUnc) { realPath = uri.LocalPath; // Will continue to load later with the regular file load part below... } else { string scheme = uri.Scheme.ToLowerInvariant(); if (scheme != "http" && scheme != "file" && scheme != "https") { Logging.LogDisplay.WriteLine("The ExternalLibrary path {0} is not a valid Uri scheme.", Path); return list; } else { if (uri.AbsolutePath.EndsWith("dna", StringComparison.InvariantCultureIgnoreCase)) { DnaLibrary lib = DnaLibrary.LoadFrom(uri); if (lib == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: DnaLibrary could not be loaded."); return list; } // CONSIDER: Should we add a resolve story for .dna files at Uris? return lib.GetAssemblies(null); // No explicit resolve path } else { // Load as a regular assembly - TypeLib not supported. list.Add(new ExportedAssembly(Assembly.LoadFrom(Path), ExplicitExports, ComServer, false, null, dnaLibrary)); return list; } } } } // Keep trying with the current value of realPath. string resolvedPath = DnaLibrary.ResolvePath(realPath, pathResolveRoot); if (resolvedPath == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: The library could not be found at this location."); return list; } if (System.IO.Path.GetExtension(resolvedPath).ToUpperInvariant() == ".DNA") { // Load as a DnaLibrary DnaLibrary lib = DnaLibrary.LoadFrom(resolvedPath); if (lib == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: DnaLibrary could not be loaded."); return list; } string pathResolveRelative = System.IO.Path.GetDirectoryName(resolvedPath); return lib.GetAssemblies(pathResolveRelative); } else { Assembly assembly; // Load as a regular assembly if (LoadFromBytes) { byte[] bytes = File.ReadAllBytes(resolvedPath); string pdbPath = System.IO.Path.ChangeExtension(resolvedPath, "pdb"); if (File.Exists(pdbPath)) { byte[] pdbBytes = File.ReadAllBytes(pdbPath); assembly = Assembly.Load(bytes, pdbBytes); } else { assembly = Assembly.Load(bytes); } } else { assembly = Assembly.LoadFrom(resolvedPath); } string resolvedTypeLibPath = null; if (!string.IsNullOrEmpty(TypeLibPath)) { resolvedTypeLibPath = DnaLibrary.ResolvePath(TypeLibPath, pathResolveRoot); // null is unresolved if (resolvedTypeLibPath == null && resolvedPath != null) { resolvedTypeLibPath = DnaLibrary.ResolvePath(TypeLibPath, System.IO.Path.GetDirectoryName(resolvedPath)); } } else { // Check for .tlb with same name next to resolvedPath string tlbCheck = System.IO.Path.ChangeExtension(resolvedPath, "tlb"); if (System.IO.File.Exists(tlbCheck)) { resolvedTypeLibPath = tlbCheck; } } list.Add(new ExportedAssembly(assembly, ExplicitExports, ComServer, false, resolvedTypeLibPath, dnaLibrary)); return list; } } catch (Exception e) { // Assembly could not be loaded. LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: " + e.Message); return list; } }
internal List<ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary) { List<ExportedAssembly> list = new List<ExportedAssembly>(); try { string realPath = Path; if (Path.StartsWith("packed:")) { // The ExternalLibrary is packed. // We'll have to load it from resources. string resourceName = Path.Substring(7); if (Path.ToUpperInvariant().EndsWith(".DNA")) { byte[] dnaContent = ExcelIntegration.GetDnaFileBytes(resourceName); DnaLibrary lib = DnaLibrary.LoadFrom(dnaContent, pathResolveRoot); if (lib == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: Packed DnaLibrary could not be loaded."); return list; } return lib.GetAssemblies(pathResolveRoot); } else { // DOCUMENT: TypeLibPath which is a resource in a library is denoted as fileName.dll\4 // For packed assemblies, we set TypeLibPath="packed:2" string typeLibPath = null; if (!string.IsNullOrEmpty(TypeLibPath) && TypeLibPath.StartsWith("packed:")) { typeLibPath = DnaLibrary.XllPath + @"\" + TypeLibPath.Substring(7); } // It would be nice to check here whether the assembly is loaded already. // But because of the name mangling in the packing we can't easily check. // So we make the following assumptions: // 1. Packed assemblies won't also be loadable from files (else they might be loaded twice) // 2. ExternalLibrary loads will happen before reference loads via AssemblyResolve. // Under these assumptions we should not have assemblies loaded more than once, // even if not checking here. byte[] rawAssembly = ExcelIntegration.GetAssemblyBytes(resourceName); Assembly assembly = Assembly.Load(rawAssembly); list.Add(new ExportedAssembly(assembly, ExplicitExports, ComServer, false, typeLibPath, dnaLibrary)); return list; } } if (Uri.IsWellFormedUriString(Path, UriKind.Absolute)) { // Here is support for loading ExternalLibraries from http. Uri uri = new Uri(Path, UriKind.Absolute); if (uri.IsUnc) { realPath = uri.LocalPath; // Will continue to load later with the regular file load part below... } else { string scheme = uri.Scheme.ToLowerInvariant(); if (scheme != "http" && scheme != "file" && scheme != "https") { Logging.LogDisplay.WriteLine("The ExternalLibrary path {0} is not a valid Uri scheme.", Path); return list; } else { if (uri.AbsolutePath.EndsWith("dna", StringComparison.InvariantCultureIgnoreCase)) { DnaLibrary lib = DnaLibrary.LoadFrom(uri); if (lib == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: DnaLibrary could not be loaded."); return list; } // CONSIDER: Should we add a resolve story for .dna files at Uris? return lib.GetAssemblies(null); // No explicit resolve path } else { // Load as a regular assembly - TypeLib not supported. Assembly assembly = Assembly.LoadFrom(Path); list.Add(new ExportedAssembly(assembly, ExplicitExports, ComServer, false, null, dnaLibrary)); return list; } } } } // Keep trying with the current value of realPath. string resolvedPath = DnaLibrary.ResolvePath(realPath, pathResolveRoot); if (resolvedPath == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: The library could not be found at this location."); return list; } if (System.IO.Path.GetExtension(resolvedPath).ToUpperInvariant() == ".DNA") { // Load as a DnaLibrary DnaLibrary lib = DnaLibrary.LoadFrom(resolvedPath); if (lib == null) { LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: DnaLibrary could not be loaded."); return list; } string pathResolveRelative = System.IO.Path.GetDirectoryName(resolvedPath); return lib.GetAssemblies(pathResolveRelative); } else { Assembly assembly; // Load as a regular assembly // First check if it is already loaded (e.g. as a reference from another assembly) // DOCUMENT: Some cases might still have assemblies loaded more than once. // E.g. for an assembly that is both ExternalLibrary and references from another assembly, // having the assembly LoadFromBytes and in the file system would load it twice, // because LoadFromBytes here happens before the .NET loaders assembly resolution. string assemblyName = System.IO.Path.GetFileNameWithoutExtension(resolvedPath); assembly = GetAssemblyIfLoaded(assemblyName); if (assembly == null) { // Really have to load it. if (LoadFromBytes) { // We need to be careful here to not re-load the assembly if it had already been loaded, // e.g. as a dependency of an assembly loaded earlier. // In that case we won't be able to have the library 'LoadFromBytes'. byte[] bytes = File.ReadAllBytes(resolvedPath); string pdbPath = System.IO.Path.ChangeExtension(resolvedPath, "pdb"); if (File.Exists(pdbPath)) { byte[] pdbBytes = File.ReadAllBytes(pdbPath); assembly = Assembly.Load(bytes, pdbBytes); } else { assembly = Assembly.Load(bytes); } } else { assembly = Assembly.LoadFrom(resolvedPath); } } string resolvedTypeLibPath = null; if (!string.IsNullOrEmpty(TypeLibPath)) { resolvedTypeLibPath = DnaLibrary.ResolvePath(TypeLibPath, pathResolveRoot); // null is unresolved if (resolvedTypeLibPath == null) { resolvedTypeLibPath = DnaLibrary.ResolvePath(TypeLibPath, System.IO.Path.GetDirectoryName(resolvedPath)); } } else { // Check for .tlb with same name next to resolvedPath string tlbCheck = System.IO.Path.ChangeExtension(resolvedPath, "tlb"); if (System.IO.File.Exists(tlbCheck)) { resolvedTypeLibPath = tlbCheck; } } list.Add(new ExportedAssembly(assembly, ExplicitExports, ComServer, false, resolvedTypeLibPath, dnaLibrary)); return list; } } catch (Exception e) { // Assembly could not be loaded. LogDisplay.WriteLine("External library could not be registered - Path: " + Path); LogDisplay.WriteLine(" Error: " + e.Message); return list; } }
// Called via Reflection from Loader internal static void Initialize(string xllPath) { ExcelDnaUtil.Initialize(); // Set up window handle Logging.TraceLogger.Initialize(); DnaLibrary.InitializeRootLibrary(xllPath); }
internal static void DeInitialize() { // Called to shut down the Add-In. // Free whatever possible currentLibrary = null; }
// Called via Reflection from Loader internal static void DeInitialize() { DnaLibrary.DeInitialize(); }
internal List <ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary) { List <ExportedAssembly> list = new List <ExportedAssembly>(); try { string realPath = Path; if (Path.StartsWith("packed:")) { // The ExternalLibrary is packed. // We'll have to load it from resources. string resourceName = Path.Substring(7); if (Path.EndsWith(".DNA", StringComparison.OrdinalIgnoreCase)) { byte[] dnaContent = ExcelIntegration.GetDnaFileBytes(resourceName); DnaLibrary lib = DnaLibrary.LoadFrom(dnaContent, pathResolveRoot); if (lib == null) { Logger.Initialization.Error("External library could not be registered - Path: {0}\r\n - Packed DnaLibrary could not be loaded", Path); return(list); } return(lib.GetAssemblies(pathResolveRoot)); } else { // DOCUMENT: TypeLibPath which is a resource in a library is denoted as fileName.dll\4 // For packed assemblies, we set TypeLibPath="packed:2" string typeLibPath = null; if (!string.IsNullOrEmpty(TypeLibPath) && TypeLibPath.StartsWith("packed:")) { typeLibPath = DnaLibrary.XllPath + @"\" + TypeLibPath.Substring(7); } // It would be nice to check here whether the assembly is loaded already. // But because of the name mangling in the packing we can't easily check. // So we make the following assumptions: // 1. Packed assemblies won't also be loadable from files (else they might be loaded twice) // 2. ExternalLibrary loads will happen before reference loads via AssemblyResolve. // Under these assumptions we should not have assemblies loaded more than once, // even if not checking here. byte[] rawAssembly = ExcelIntegration.GetAssemblyBytes(resourceName); byte[] rawPdb = ExcelIntegration.GetPdbBytes(resourceName); Assembly assembly = ExcelIntegration.LoadFromAssemblyBytes(rawAssembly, rawPdb); list.Add(new ExportedAssembly(assembly, ExplicitExports, ExplicitRegistration, ComServer, false, typeLibPath, dnaLibrary)); return(list); } } if (Uri.IsWellFormedUriString(Path, UriKind.Absolute)) { // Here is support for loading ExternalLibraries from http. Uri uri = new Uri(Path, UriKind.Absolute); if (uri.IsUnc) { realPath = uri.LocalPath; // Will continue to load later with the regular file load part below... } else { string scheme = uri.Scheme.ToLowerInvariant(); if (scheme != "http" && scheme != "file" && scheme != "https") { Logger.Initialization.Error("The ExternalLibrary path {0} is not a valid Uri scheme.", Path); return(list); } else { if (uri.AbsolutePath.EndsWith("dna", StringComparison.InvariantCultureIgnoreCase)) { DnaLibrary lib = DnaLibrary.LoadFrom(uri); if (lib == null) { Logger.Initialization.Error("External library could not be registered - Path: {0} - DnaLibrary could not be loaded" + Path); return(list); } // CONSIDER: Should we add a resolve story for .dna files at Uris? return(lib.GetAssemblies(null)); // No explicit resolve path } else { // Load as a regular assembly - TypeLib not supported. Assembly assembly = ExcelIntegration.LoadFromAssemblyPath(Path); list.Add(new ExportedAssembly(assembly, ExplicitExports, ExplicitRegistration, ComServer, false, null, dnaLibrary)); return(list); } } } } // Keep trying with the current value of realPath. string resolvedPath = DnaLibrary.ResolvePath(realPath, pathResolveRoot); if (resolvedPath == null) { Logger.Initialization.Error("External library could not be registered - Path: {0} - The library could not be found at this location" + Path); return(list); } if (System.IO.Path.GetExtension(resolvedPath).Equals(".DNA", StringComparison.OrdinalIgnoreCase)) { // Load as a DnaLibrary DnaLibrary lib = DnaLibrary.LoadFrom(resolvedPath); if (lib == null) { Logger.Initialization.Error("External library could not be registered - Path: {0} - DnaLibrary could not be loaded" + Path); return(list); } string pathResolveRelative = System.IO.Path.GetDirectoryName(resolvedPath); return(lib.GetAssemblies(pathResolveRelative)); } else { Assembly assembly; // Load as a regular assembly // First check if it is already loaded (e.g. as a reference from another assembly) // DOCUMENT: Some cases might still have assemblies loaded more than once. // E.g. for an assembly that is both ExternalLibrary and references from another assembly, // having the assembly LoadFromBytes and in the file system would load it twice, // because LoadFromBytes here happens before the .NET loaders assembly resolution. string assemblyName = System.IO.Path.GetFileNameWithoutExtension(resolvedPath); assembly = GetAssemblyIfLoaded(assemblyName); if (assembly == null) { // Really have to load it. if (LoadFromBytes) { // We need to be careful here to not re-load the assembly if it had already been loaded, // e.g. as a dependency of an assembly loaded earlier. // In that case we won't be able to have the library 'LoadFromBytes'. byte[] bytes = File.ReadAllBytes(resolvedPath); byte[] pdbBytes = null; string pdbPath = System.IO.Path.ChangeExtension(resolvedPath, "pdb"); if (File.Exists(pdbPath)) { pdbBytes = File.ReadAllBytes(pdbPath); } assembly = ExcelIntegration.LoadFromAssemblyBytes(bytes, pdbBytes); } else { assembly = ExcelIntegration.LoadFromAssemblyPath(resolvedPath); } } string resolvedTypeLibPath = null; if (!string.IsNullOrEmpty(TypeLibPath)) { resolvedTypeLibPath = DnaLibrary.ResolvePath(TypeLibPath, pathResolveRoot); // null is unresolved if (resolvedTypeLibPath == null) { resolvedTypeLibPath = DnaLibrary.ResolvePath(TypeLibPath, System.IO.Path.GetDirectoryName(resolvedPath)); } } else { // Check for .tlb with same name next to resolvedPath string tlbCheck = System.IO.Path.ChangeExtension(resolvedPath, "tlb"); if (System.IO.File.Exists(tlbCheck)) { resolvedTypeLibPath = tlbCheck; } } list.Add(new ExportedAssembly(assembly, ExplicitExports, ExplicitRegistration, ComServer, false, resolvedTypeLibPath, dnaLibrary)); return(list); } } catch (Exception e) { // Assembly could not be loaded. Logger.Initialization.Error(e, "External library could not be registered - Path: {0}", Path); return(list); } }
internal static void Initialize() { ExcelDnaUtil.Initialize(); DnaLibrary.Initialize(); }