private static void LoadIntegration() { Assembly integrationAssembly = Assembly.Load("ExcelDna.Integration"); Type integrationType = integrationAssembly.GetType("ExcelDna.Integration.Integration"); // Get the methods that need to be called from the integration assembly MethodInfo tryExcelImplMethod = typeof(XlCallImpl).GetMethod("TryExcelImpl", BindingFlags.Static | BindingFlags.Public); Type tryExcelImplDelegateType = integrationAssembly.GetType("ExcelDna.Integration.TryExcelImplDelegate"); Delegate tryExcelImplDelegate = Delegate.CreateDelegate(tryExcelImplDelegateType, tryExcelImplMethod); integrationType.InvokeMember("SetTryExcelImpl", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { tryExcelImplDelegate }); MethodInfo registerMethodsMethod = typeof(XlAddIn).GetMethod("RegisterMethods", BindingFlags.Static | BindingFlags.Public); Type registerMethodsDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterMethodsDelegate"); Delegate registerMethodsDelegate = Delegate.CreateDelegate(registerMethodsDelegateType, registerMethodsMethod); integrationType.InvokeMember("SetRegisterMethods", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerMethodsDelegate }); MethodInfo getAssemblyBytesMethod = typeof(AssemblyManager).GetMethod("GetAssemblyBytes", BindingFlags.Static | BindingFlags.NonPublic); Type getAssemblyBytesDelegateType = integrationAssembly.GetType("ExcelDna.Integration.GetAssemblyBytesDelegate"); Delegate getAssemblyBytesDelegate = Delegate.CreateDelegate(getAssemblyBytesDelegateType, getAssemblyBytesMethod); integrationType.InvokeMember("SetGetAssemblyBytesDelegate", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { getAssemblyBytesDelegate }); // set up helpers for future calls IntegrationHelpers.Bind(integrationAssembly); IntegrationMarshalHelpers.Bind(integrationAssembly); }
private static void LoadIntegration() { // Get the assembly and ExcelIntegration type - will be loaded from file or from packed resources via AssemblyManager.AssemblyResolve. Assembly integrationAssembly = Assembly.Load("ExcelDna.Integration"); // Check if ExcelDna.Integration was loaded from the Global Assembly Cache if (integrationAssembly.GlobalAssemblyCache) { // Prevent using the version in the GAC to avoid add-ins using the wrong version and breaking // https://github.com/Excel-DNA/ExcelDna/pull/250#issuecomment-508642133 throw new InvalidOperationException("ExcelDna.Integration was loaded from Global Assembly Cache, and that's not allowed."); } Type integrationType = integrationAssembly.GetType("ExcelDna.Integration.ExcelIntegration"); // Check the version declared in the ExcelIntegration class int integrationVersion = (int)integrationType.InvokeMember("GetExcelIntegrationVersion", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, null); if (integrationVersion != ExcelIntegrationVersion) { // This is not the version we are expecting! throw new InvalidOperationException("Invalid ExcelIntegration version detected."); } // Get the methods that need to be called from the integration assembly MethodInfo tryExcelImplMethod = typeof(XlCallImpl).GetMethod("TryExcelImpl", BindingFlags.Static | BindingFlags.Public); Type tryExcelImplDelegateType = integrationAssembly.GetType("ExcelDna.Integration.TryExcelImplDelegate"); Delegate tryExcelImplDelegate = Delegate.CreateDelegate(tryExcelImplDelegateType, tryExcelImplMethod); integrationType.InvokeMember("SetTryExcelImpl", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { tryExcelImplDelegate }); MethodInfo registerMethodsMethod = typeof(XlRegistration).GetMethod("RegisterMethods", BindingFlags.Static | BindingFlags.Public); Type registerMethodsDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterMethodsDelegate"); Delegate registerMethodsDelegate = Delegate.CreateDelegate(registerMethodsDelegateType, registerMethodsMethod); integrationType.InvokeMember("SetRegisterMethods", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerMethodsDelegate }); MethodInfo registerWithAttMethod = typeof(XlRegistration).GetMethod("RegisterMethodsWithAttributes", BindingFlags.Static | BindingFlags.Public); Type registerWithAttDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterMethodsWithAttributesDelegate"); Delegate registerWithAttDelegate = Delegate.CreateDelegate(registerWithAttDelegateType, registerWithAttMethod); integrationType.InvokeMember("SetRegisterMethodsWithAttributes", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerWithAttDelegate }); MethodInfo registerDelAttMethod = typeof(XlRegistration).GetMethod("RegisterDelegatesWithAttributes", BindingFlags.Static | BindingFlags.Public); Type registerDelAttDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterDelegatesWithAttributesDelegate"); Delegate registerDelAttDelegate = Delegate.CreateDelegate(registerDelAttDelegateType, registerDelAttMethod); integrationType.InvokeMember("SetRegisterDelegatesWithAttributes", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerDelAttDelegate }); MethodInfo getResourceBytesMethod = typeof(AssemblyManager).GetMethod("GetResourceBytes", BindingFlags.Static | BindingFlags.NonPublic); Type getResourceBytesDelegateType = integrationAssembly.GetType("ExcelDna.Integration.GetResourceBytesDelegate"); Delegate getResourceBytesDelegate = Delegate.CreateDelegate(getResourceBytesDelegateType, getResourceBytesMethod); integrationType.InvokeMember("SetGetResourceBytesDelegate", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { getResourceBytesDelegate }); // set up helpers for future calls IntegrationHelpers.Bind(integrationAssembly, integrationType); IntegrationMarshalHelpers.Bind(integrationAssembly); }
private static void LoadIntegration() { // Get the assembly and ExcelIntegration type - will be loaded from file or from packed resources via AssemblyManager.AssemblyResolve. Assembly integrationAssembly = Assembly.Load("ExcelDna.Integration"); Type integrationType = integrationAssembly.GetType("ExcelDna.Integration.ExcelIntegration"); // Check the version declared in the ExcelIntegration class int integrationVersion = (int)integrationType.InvokeMember("GetExcelIntegrationVersion", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, null); if (integrationVersion != ExcelIntegrationVersion) { // This is not the version we are expecting! throw new InvalidOperationException("Invalid ExcelIntegration version detected."); } // Get the methods that need to be called from the integration assembly MethodInfo tryExcelImplMethod = typeof(XlCallImpl).GetMethod("TryExcelImpl", BindingFlags.Static | BindingFlags.Public); Type tryExcelImplDelegateType = integrationAssembly.GetType("ExcelDna.Integration.TryExcelImplDelegate"); Delegate tryExcelImplDelegate = Delegate.CreateDelegate(tryExcelImplDelegateType, tryExcelImplMethod); integrationType.InvokeMember("SetTryExcelImpl", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { tryExcelImplDelegate }); MethodInfo registerMethodsMethod = typeof(XlRegistration).GetMethod("RegisterMethods", BindingFlags.Static | BindingFlags.Public); Type registerMethodsDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterMethodsDelegate"); Delegate registerMethodsDelegate = Delegate.CreateDelegate(registerMethodsDelegateType, registerMethodsMethod); integrationType.InvokeMember("SetRegisterMethods", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerMethodsDelegate }); MethodInfo registerWithAttMethod = typeof(XlRegistration).GetMethod("RegisterMethodsWithAttributes", BindingFlags.Static | BindingFlags.Public); Type registerWithAttDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterMethodsWithAttributesDelegate"); Delegate registerWithAttDelegate = Delegate.CreateDelegate(registerWithAttDelegateType, registerWithAttMethod); integrationType.InvokeMember("SetRegisterMethodsWithAttributes", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerWithAttDelegate }); MethodInfo registerDelAttMethod = typeof(XlRegistration).GetMethod("RegisterDelegatesWithAttributes", BindingFlags.Static | BindingFlags.Public); Type registerDelAttDelegateType = integrationAssembly.GetType("ExcelDna.Integration.RegisterDelegatesWithAttributesDelegate"); Delegate registerDelAttDelegate = Delegate.CreateDelegate(registerDelAttDelegateType, registerDelAttMethod); integrationType.InvokeMember("SetRegisterDelegatesWithAttributes", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { registerDelAttDelegate }); MethodInfo getFuncRegInfoMethod = typeof(XlRegistration).GetMethod("GetFunctionRegistrationInfo", BindingFlags.Static | BindingFlags.Public); Type getFuncRegInfoDelegateType = integrationAssembly.GetType("ExcelDna.Integration.GetFunctionRegistrationInfoDelegate"); Delegate getFuncRegInfoDelegate = Delegate.CreateDelegate(getFuncRegInfoDelegateType, getFuncRegInfoMethod); integrationType.InvokeMember("SetGetFunctionRegistrationInfo", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { getFuncRegInfoDelegate }); MethodInfo getResourceBytesMethod = typeof(AssemblyManager).GetMethod("GetResourceBytes", BindingFlags.Static | BindingFlags.NonPublic); Type getResourceBytesDelegateType = integrationAssembly.GetType("ExcelDna.Integration.GetResourceBytesDelegate"); Delegate getResourceBytesDelegate = Delegate.CreateDelegate(getResourceBytesDelegateType, getResourceBytesMethod); integrationType.InvokeMember("SetGetResourceBytesDelegate", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { getResourceBytesDelegate }); // set up helpers for future calls IntegrationHelpers.Bind(integrationAssembly, integrationType); IntegrationMarshalHelpers.Bind(integrationAssembly); }
internal static IntPtr XlAddInManagerInfo12(IntPtr pXloperAction12) { Debug.WriteLine("In XlAddIn.XlAddInManagerInfo12"); ICustomMarshaler m = XlObject12Marshaler.GetInstance(""); object action = m.MarshalNativeToManaged(pXloperAction12); object result; if ((action is double && (double)action == 1.0)) { InitializeIntegration(); result = IntegrationHelpers.DnaLibraryGetName(); } else { result = IntegrationMarshalHelpers.GetExcelErrorObject(IntegrationMarshalHelpers.ExcelError_ExcelErrorValue); } return(m.MarshalManagedToNative(result)); }
// NOTE: We are not currently removing the functions from the Jmp array // That would be needed to do a proper per-method deregistration, // together with a garbage-collectable story for the wrapper methods and delegates, // instead of the currently runtime-compiled and loaded assemblies. internal static void UnregisterMethods() { object xlCallResult; // Remove menus and ShortCuts IntegrationHelpers.RemoveCommandMenus(); UnregisterShortCuts(); // Now take out the methods foreach (XlMethodInfo mi in registeredMethods) { if (mi.IsCommand) { // Clear the name and unregister XlCallImpl.TryExcelImpl(XlCallImpl.xlfSetName, out xlCallResult, mi.Name); XlCallImpl.TryExcelImpl(XlCallImpl.xlfUnregister, out xlCallResult, mi.RegisterId); } else { // And Unregister the real function XlCallImpl.TryExcelImpl(XlCallImpl.xlfUnregister, out xlCallResult, mi.RegisterId); // I follow the advice from X-Cell website to get function out of Wizard (with fix from kh) XlCallImpl.TryExcelImpl(XlCallImpl.xlfRegister, out xlCallResult, XlAddIn.PathXll, "xlAutoRemove", "I", mi.Name, IntegrationMarshalHelpers.GetExcelMissingValue(), 2); if (xlCallResult is double) { double fakeRegisterId = (double)xlCallResult; XlCallImpl.TryExcelImpl(XlCallImpl.xlfSetName, out xlCallResult, mi.Name); XlCallImpl.TryExcelImpl(XlCallImpl.xlfUnregister, out xlCallResult, fakeRegisterId); } } } registeredMethods.Clear(); registrationInfo.Clear(); }
private Delegate CreateMethodDelegate(MethodInfo targetMethod, Type delegateType) { // Check whether we can skip wrapper if (IsExceptionSafe && Array.TrueForAll(Parameters, delegate(XlParameterInfo pi){ return(pi.BoxedValueType == null); }) && (IsCommand || ReturnType.BoxedValueType == null)) { // Create the delegate directly return(Delegate.CreateDelegate(delegateType, targetMethod)); } // Else we create a dynamic wrapper Type[] paramTypes = Array.ConvertAll <XlParameterInfo, Type>(Parameters, delegate(XlParameterInfo pi) { return(pi.DelegateParamType); }); DynamicMethod wrapper = new DynamicMethod( string.Format("Wrapped_f{0}_{1}", Index, targetMethod.Name), IsCommand ? typeof(void) : ReturnType.DelegateParamType, paramTypes, typeof(object), true); ILGenerator wrapIL = wrapper.GetILGenerator(); Label endOfMethod = wrapIL.DefineLabel(); LocalBuilder retobj = null; if (!IsCommand) { // Make a local to contain the return value retobj = wrapIL.DeclareLocal(ReturnType.DelegateParamType); } if (!IsExceptionSafe) { // Start the Try block wrapIL.BeginExceptionBlock(); } // Generate the body // push all the arguments for (byte i = 0; i < paramTypes.Length; i++) { wrapIL.Emit(OpCodes.Ldarg_S, i); XlParameterInfo pi = Parameters[i]; if (pi.BoxedValueType != null) { wrapIL.Emit(OpCodes.Unbox_Any, pi.BoxedValueType); } } // Call the real method wrapIL.EmitCall(OpCodes.Call, targetMethod, null); if (!IsCommand && ReturnType.BoxedValueType != null) { // Box the return value (which is on the stack) wrapIL.Emit(OpCodes.Box, ReturnType.BoxedValueType); } if (!IsCommand) { // Store the return value into the local variable wrapIL.Emit(OpCodes.Stloc_S, retobj); } if (!IsExceptionSafe) { wrapIL.Emit(OpCodes.Leave_S, endOfMethod); wrapIL.BeginCatchBlock(typeof(object)); wrapIL.Emit(OpCodes.Pop); if (!IsCommand && ReturnType.DelegateParamType == typeof(object)) { // Create a boxed Excel error value, and set the return object to it wrapIL.Emit(OpCodes.Ldc_I4, IntegrationMarshalHelpers.ExcelError_ExcelErrorValue); wrapIL.Emit(OpCodes.Box, IntegrationMarshalHelpers.GetExcelErrorType()); wrapIL.Emit(OpCodes.Stloc_S, retobj); } wrapIL.EndExceptionBlock(); } wrapIL.MarkLabel(endOfMethod); if (!IsCommand) { // Push the return value wrapIL.Emit(OpCodes.Ldloc_S, retobj); } wrapIL.Emit(OpCodes.Ret); return(wrapper.CreateDelegate(delegateType));; }
internal static void UnregisterMethods() { object xlCallResult; // Remove menus IntegrationHelpers.RemoveCommandMenus(); // Now take out the methods foreach (XlMethodInfo mi in registeredMethods) { if (mi.IsCommand) { XlCallImpl.TryExcelImpl(XlCallImpl.xlfSetName, out xlCallResult, mi.Name, ""); } else { // I follow the advice from X-Cell website // to get function out of Wizard XlCallImpl.TryExcelImpl(XlCallImpl.xlfRegister, out xlCallResult, pathXll, "xlAutoRemove", "J", mi.Name, IntegrationMarshalHelpers.GetExcelMissingValue(), 0); } XlCallImpl.TryExcelImpl(XlCallImpl.xlfUnregister, out xlCallResult, mi.RegisterId); } registeredMethods.Clear(); }