// This is the helper macro that runs (on the main thread) void SyncMacro(double _unused_) { // Check for timer and disable if (_timerId != 0) { KillTimer(new HandleRef(_syncWindow, _syncWindow.Handle), _timerId); _timerId = 0; // No race condition between the check and the reset here, since we're always on the main thread. } // Run everything currently in the queue _isRunningMacros = true; while (_isRunningMacros) { SendOrPostCallback work = null; object state = null; lock (_sendOrPostLock) { _isRunningMacros = _postCallbacks.Count > 0; if (_isRunningMacros) { work = _postCallbacks.Dequeue(); state = _postStates.Dequeue(); } else { // set flag that we need to post again for work // and exit _syncPosted = false; return; } } try { work(state); } catch (Exception ex) { UnhandledExceptionHandler handler = ExcelIntegration.GetRegisterUnhandledExceptionHandler(); if (handler != null) { try { handler(ex); } catch (Exception uehex) { Logger.Runtime.Error(ex, "Unhandled exception in async delegate call."); Logger.Runtime.Error(uehex, "Unhandled exception in UnhandledExceptionHandler after async delegate call."); } } else { Logger.Runtime.Error(ex, "Unhandled exception in async delegate call."); } } } }
// Only called for the Root DnaLibrary. internal void AutoOpen() { // Register special RegistrationInfo function RegistrationInfo.Register(); SynchronizationManager.Install(true); // Register my Methods - should this also go into the delayed call? ExcelIntegration.RegisterMethods(_methods); // We defer the rest of the load until we have an Application object... ExcelAsyncUtil.QueueAsMacro(AutoOpenImpl); }
public Bitmap GetImage(string imageId) { // We expect these to be small images. // First check if imageId is in the DnaLibrary's Image list. // DOCUMENT: Case sensitive match. foreach (Image image in Images) { if (image.Name == imageId && image.Path != null) { byte[] imageBytes = null; System.Drawing.Image imageLoaded; if (image.Path.StartsWith("packed:")) { string resourceName = image.Path.Substring(7); imageBytes = ExcelIntegration.GetImageBytes(resourceName); } else { string imagePath = ResolvePath(image.Path); if (imagePath == null) { // This is the image but we could not find it !? Logger.Initialization.Warn("DnaLibrary.GetImage - For image {0} the path resolution failed: {1}", image.Name, image.Path); return(null); } imageBytes = File.ReadAllBytes(imagePath); } using (MemoryStream ms = new MemoryStream(imageBytes, false)) { imageLoaded = System.Drawing.Image.FromStream(ms); if (imageLoaded is Bitmap) { return((Bitmap)imageLoaded); } Logger.Initialization.Warn("DnaLibrary.GetImage - Image {0} read from {1} was not a bitmap!?", image.Name, image.Path); } } } return(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; _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"); }
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); } }
public static void RegisterUnhandledExceptionHandler(UnhandledExceptionHandler h) { ExcelIntegration.RegisterUnhandledExceptionHandler(h); }
public static void RegisterMethods(List <MethodInfo> methods) { ExcelIntegration.RegisterMethods(methods); }
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); }
public override void RegisterMethods(List <MethodInfo> methods) { ExcelIntegration.RegisterMethods(methods); }
public override void RegisterUnhandledExceptionHandler(UnhandledExceptionHandler exceptionHandler) { ExcelIntegration.RegisterUnhandledExceptionHandler(exceptionHandler); }
// Calls the Excel-DNA UnhandledExceptionHandler (which by default returns #VALUE to Excel). public override bool SetException(Exception exception) { object result = ExcelIntegration.HandleUnhandledException(exception); return(SetResult(result)); }
static int CallPenHelper(int wCode, ref XlCall.FmlaInfo fmlaInfo) { return(ExcelIntegration.LPenHelper(XlCall.xlGetFmlaInfo, ref fmlaInfo)); }