@@ -42,6 +42,7 @@ public static class IntelliSenseServer
4242
4343 const string ControlMessageActivate = "ACTIVATE" ;
4444 const string ControlMessageDeactivate = "DEACTIVATE" ;
45+ const string ControlMessageRefresh = "REFRESH" ;
4546
4647 // Info for registration
4748 // _serverId is a transient ID to identify this IntelliSense server - we could have used the ExcelDnaUtil.XllGuid one too,
@@ -95,6 +96,25 @@ public static void Register()
9596 Logger . Initialization . Info ( "IntelliSenseServer.Register End" ) ;
9697 }
9798
99+ // Invokes a Refresh on the Active server (if there is on)
100+ // Must be called from a macro context
101+ // Appropriate for calling after registering extra methods in an add-in
102+ public static void Refresh ( )
103+ {
104+ Logger . Initialization . Info ( $ "IntelliSenseServer.Refresh Begin") ;
105+ if ( _isActive )
106+ {
107+ RefreshProviders ( ) ;
108+ }
109+ else
110+ {
111+ RegistrationInfo registrationInfo = GetActiveRegistrationInfo ( ) ;
112+ if ( registrationInfo != null )
113+ RefreshServer ( registrationInfo ) ;
114+ }
115+ Logger . Initialization . Info ( $ "IntelliSenseServer.Refresh End") ;
116+ }
117+
98118 private static void CurrentDomain_ProcessExit ( object sender , EventArgs e )
99119 {
100120 Logger . Initialization . Verbose ( "IntelliSenseServer ProcessExit Begin" ) ;
@@ -170,6 +190,22 @@ internal static bool Deactivate()
170190 }
171191 }
172192
193+ // Called directly from Refresh or via the control function
194+ internal static void RefreshProviders ( )
195+ {
196+ Logger . Initialization . Info ( $ "IntelliSenseServer.RefreshProviders") ;
197+ try
198+ {
199+ Debug . Assert ( _helper != null ) ;
200+ _helper . RefreshProviders ( ) ;
201+ }
202+ catch ( Exception ex )
203+ {
204+ // TODO: Log
205+ Logger . Initialization . Error ( $ "IntelliSenseServer.RefreshProviders error: { ex } ") ;
206+ }
207+ }
208+
173209 // NOTE: Please do not remove this safety mechanism in custom versions.
174210 // The IntelliSense mechanism is co-operative between independent add-ins.
175211 // Allowing a safe disable options is important to support future versions, and protect against problematic bugs.
@@ -200,7 +236,7 @@ static bool ActivateServer(RegistrationInfo registrationInfo)
200236 // Suppress errors if things go wrong, including unexpected return types.
201237 try
202238 {
203- var result = ExcelDna . Integration . XlCall . Excel ( ExcelDna . Integration . XlCall . xlUDF , registrationInfo . GetControlMacroName ( ) , ControlMessageDeactivate ) ;
239+ var result = ExcelDna . Integration . XlCall . Excel ( ExcelDna . Integration . XlCall . xlUDF , registrationInfo . GetControlMacroName ( ) , ControlMessageActivate ) ;
204240 return ( bool ) result ;
205241 }
206242 catch ( Exception ex )
@@ -232,6 +268,26 @@ static bool DeactivateServer(RegistrationInfo registrationInfo)
232268 }
233269 }
234270
271+ static bool RefreshServer ( RegistrationInfo registrationInfo )
272+ {
273+ // Suppress errors if things go wrong, including unexpected return types.
274+ try
275+ {
276+ var result = ExcelDna . Integration . XlCall . Excel ( ExcelDna . Integration . XlCall . xlUDF , registrationInfo . GetControlMacroName ( ) , ControlMessageRefresh ) ;
277+ if ( result is ExcelError )
278+ {
279+ Logger . Initialization . Error ( $ "IntelliSenseServer { registrationInfo . ToRegistrationString ( ) } could not be deactivated.") ;
280+ return false ;
281+ }
282+ return ( bool ) result ;
283+ }
284+ catch ( Exception ex )
285+ {
286+ Logger . Initialization . Error ( ex , $ "IntelliSenseServer Deactivate call for { registrationInfo . ToRegistrationString ( ) } failed.") ;
287+ return false ;
288+ }
289+ }
290+
235291 #region Registration
236292
237293 // NOTE: We have to be really careful about compatibility across versions here...
@@ -434,15 +490,28 @@ static void RegisterControlMacro()
434490 // NOTE: The name here is used by Reflection above (when registering the method with Excel)
435491 static object IntelliSenseServerControl ( object control )
436492 {
437- if ( control is string && ( string ) control == ControlMessageActivate )
493+ string controlMessage = control as string ;
494+ if ( controlMessage == ControlMessageActivate )
438495 {
439496 Debug . Print ( "IntelliSenseServer.Activate in AppDomain: " + AppDomain . CurrentDomain . FriendlyName ) ;
440- return IntelliSenseServer . Activate ( ) ;
497+ return Activate ( ) ;
441498 }
442- else if ( control is string && ( string ) control == ControlMessageDeactivate )
499+ else if ( controlMessage == ControlMessageDeactivate )
443500 {
444501 Debug . Print ( "IntelliSenseServer.Deactivate in AppDomain: " + AppDomain . CurrentDomain . FriendlyName ) ;
445- return IntelliSenseServer . Deactivate ( ) ;
502+ return Deactivate ( ) ;
503+ }
504+ else if ( controlMessage == ControlMessageRefresh )
505+ {
506+ Debug . Print ( "IntelliSenseServer.Refresh in AppDomain: " + AppDomain . CurrentDomain . FriendlyName ) ;
507+ if ( ! _isActive )
508+ {
509+ // Something went wrong...
510+ Logger . Initialization . Error ( "IntelliSenseServer Refresh call on inactive server." ) ;
511+ return false ;
512+ }
513+ RefreshProviders ( ) ;
514+ return true ;
446515 }
447516 return false ;
448517 }
0 commit comments