public static CustomTaskPane CreateCustomTaskPane(Type userControlType, string title, object parent) { //if (!typeof(System.Windows.Forms.UserControl).IsAssignableFrom(userControlType)) //{ // throw new ArgumentException("userControlType for Custom Task Pane must be derive from type System.Windows.Forms.UserControl"); //} // I could use the ProgId and ClsId of the UserControl type here. // But then the reigstration has to be persistent or coordinated, which I dislike. // It's already a problem for the RTD servers. // Users that want persistent and consistent names, can sort out registration themselves, or use the ExcelComClass support. // Then the CTP is created through the CreateCustomTaskPane("My.ProgId",...) overloads. // So when passed the type, I always synthesize a progid. // We pick a new Guid as ClassId for this add-in... Guid clsId = Guid.NewGuid(); // ...and make the ProgId from this Guid - max 39 chars. string progId = "CtpSrv." + clsId.ToString("N"); // Register UserControl // (could probably get away with RegistrationServices.RegisterTypeForComClients instead of our own ClassFactoryRegistration class) using (ProgIdRegistration progIdReg = new ProgIdRegistration(progId, clsId)) using (ClsIdRegistration clsIdReg = new ClsIdRegistration(clsId, progId)) using (ClassFactoryRegistration cf = new ClassFactoryRegistration(userControlType, clsId)) { return CreateCustomTaskPane(progId, title, parent); } }
// Forwarded from XlCall public static object RTD(string progId, string server, params string[] topics) { // Check if this is any of our business. if (!string.IsNullOrEmpty(server) || !registeredRtdServerTypes.ContainsKey(progId)) { // Just pass on to Excel. return CallRTD(progId, null, topics); } // Check if already loaded. if (loadedRtdServers.ContainsKey(progId)) { // Call Excel using the synthetic RtdSrv.xxx (or actual from attribute) ProgId return CallRTD(loadedRtdServers[progId], null, topics); } // Not loaded already - need to get the Rtd server loaded // TODO: Need to reconsider registration here..... // Sometimes need stable ProgIds. Type rtdServerType = registeredRtdServerTypes[progId]; object rtdServer = Activator.CreateInstance(rtdServerType); RtdServerWrapper rtdServerWrapper = new RtdServerWrapper(rtdServer, progId); // We pick a new Guid as ClassId for this add-in... CLSID clsId = Guid.NewGuid(); // ... but take a stable ProgId from the XllPath and type's FullName - max 39 chars. // ... (bad idea - this will cause Excel to try to load this RTD server while it is not registered.) // Guid typeGuid = GetGuidFromString(DnaLibrary.XllPath + ":" + rtdServerType.FullName); // string progIdRegistered = "RtdSrv." + typeGuid.ToString("N"); // by making a fresh progId, we are sure Excel will try to load when we are ready. string progIdRegistered = "RtdSrv." + clsId.ToString("N"); Debug.Print("RTD - Using ProgId: {0} for type: {1}", progIdRegistered, rtdServerType.FullName); // Mark as loaded - ServerTerminate in the wrapper will remove. // TODO: Consider multithread race condition... loadedRtdServers[progId] = progIdRegistered; using (SingletonClassFactoryRegistration regClassFactory = new SingletonClassFactoryRegistration(rtdServerWrapper, clsId)) using (ProgIdRegistration regProgId = new ProgIdRegistration(progIdRegistered, clsId)) using (ClsIdRegistration regClsId = new ClsIdRegistration(clsId, progIdRegistered)) { return CallRTD(progIdRegistered, null, topics); } }