static readonly CultureInfo _enUsCulture = new CultureInfo(1033); // Don't know if this is useful... // Invoke Application.Run to run a macro // Returns true if it ran OK, false if not and we should retry static bool COMRunMacro(string macroName) { try { // If busy editing, don't even try to call Application.Run. if (IsInFormulaEditMode()) { return(false); } object xlApp = ExcelDnaUtil.GetApplicationNotProtectedNoThrow(); if (xlApp == null) { // Some possibilities that get us here: // * Can't get Application object at all - first time we're trying is here, no workbook open and hence C API is needed but not available // * Excel is shutting down (would have abandoned in the past, now we keep re-trying) return(false); } Type appType = xlApp.GetType(); // Now try Application.Run(macroName) if we are still alive. object result = appType.InvokeMember("Run", BindingFlags.InvokeMethod, null, xlApp, new object[] { macroName, 0.0 }, _enUsCulture); // Sometimes (e.g. when the paste live preview feature is active) Application.Run returns the integer value for E_FAIL, // and not a COM Error that is converted to an exception. if (!result.Equals(0.0)) // We expect our "void" macro to just return 0.0. { #if DEBUG // Some extra checks to see if we can understand the return values better if (!(result is int)) { Logger.Registration.Error("Unexpected return type from Application.Run(\"SyncMacro_...\") - " + result); } else { if ((int)result != E_FAIL && (int)result != E_NA) { Logger.Registration.Error("Unexpected return value from Application.Run(\"SyncMacro_...\") - " + result); } } #endif return(false); } return(true); } catch (TargetInvocationException tie) { // Deal with the COM exception that we get if the Application object does not allow us to call 'Run' right now. COMException cex = tie.InnerException as COMException; if (cex != null && IsRetry(cex)) { return(false); } // Unexpected error - very bad - we abandon the whole QueueAsMacro plan forever - the exception is handled higher up and logged throw; } }
// Only called for the Root DnaLibrary. internal void AutoOpen() { SynchronizationManager.Install(true); if (ExcelDnaUtil.GetApplicationNotProtectedNoThrow() != null) { // Proceed without undue delay AutoOpenImpl(); } else { // Some possibilities that get us here: // * Can't get Application object at all - first time we're trying is here, no workbook open and hence C API is needed but not available // * Excel is shutting down (would have abandoned in the past, now we keep re-trying) // We defer the rest of the load until we have an Application object... ExcelAsyncUtil.QueueAsMacro(AutoOpenImpl); } }