Skip to content

Commit 19a70fa

Browse files
committed
First attempt at shutdown / unload improvements
1 parent 20432dc commit 19a70fa

File tree

10 files changed

+83
-53
lines changed

10 files changed

+83
-53
lines changed

Source/ExcelDna.IntelliSense.Host/ExcelDna.IntelliSense.Host.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ xcopy "$(TargetDir)ExcelDna.IntelliSense.Host-AddIn.dna*" "$(TargetDir)ExcelDna.
7373
xcopy "$(SolutionDir)\packages\ExcelDna.AddIn.0.33.9\tools\ExcelDna64.xll" "$(TargetDir)ExcelDna.IntelliSense.Host-AddIn64.xll*" /C /Y
7474
"$(SolutionDir)\packages\ExcelDna.AddIn.0.33.9\tools\ExcelDnaPack.exe" "$(TargetDir)ExcelDna.IntelliSense.Host-AddIn.dna" /Y /O "$(TargetDir)ExcelDna.IntelliSense.xll"
7575
"$(SolutionDir)\packages\ExcelDna.AddIn.0.33.9\tools\ExcelDnaPack.exe" "$(TargetDir)ExcelDna.IntelliSense.Host-AddIn64.dna" /Y /O "$(TargetDir)ExcelDna.IntelliSense64.xll"
76-
xcopy "$(TargetDir)ExcelDna.IntelliSense.Host-AddIn.xll.config" "$(TargetDir)ExcelDna.IntelliSense.xll.config*"</PostBuildEvent>
76+
xcopy "$(TargetDir)ExcelDna.IntelliSense.Host-AddIn.xll.config" "$(TargetDir)ExcelDna.IntelliSense.xll.config*" /C /Y</PostBuildEvent>
7777
</PropertyGroup>
7878
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
7979
Other similar extension points exist, see Microsoft.Common.targets.

Source/ExcelDna.IntelliSense/IntelliSenseDisplay.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -420,22 +420,22 @@ TextLine GetArgumentDescription(IntelliSenseFunctionInfo.ArgumentInfo argumentIn
420420

421421
public void Dispose()
422422
{
423-
// TODO: How to interact with the pending event callbacks?
424-
_syncContextMain.Send(delegate
425-
{
426-
if (_descriptionToolTip != null)
427-
{
428-
_descriptionToolTip.Dispose();
429-
_descriptionToolTip = null;
430-
}
431-
if (_argumentsToolTip != null)
432-
{
433-
_argumentsToolTip.Dispose();
434-
_argumentsToolTip = null;
435-
}
436-
_uiMonitor.Dispose();
437-
}, null);
438-
423+
_uiMonitor.StateUpdatePreview -= StateUpdatePreview;
424+
_uiMonitor.StateUpdate -= StateUpdate;
425+
//// TODO: How to interact with the pending event callbacks?
426+
//_syncContextMain.Send(delegate
427+
// {
428+
// if (_descriptionToolTip != null)
429+
// {
430+
// _descriptionToolTip.Dispose();
431+
// _descriptionToolTip = null;
432+
// }
433+
// if (_argumentsToolTip != null)
434+
// {
435+
// _argumentsToolTip.Dispose();
436+
// _argumentsToolTip = null;
437+
// }
438+
// }, null);
439439
_syncContextMain = null;
440440
}
441441

Source/ExcelDna.IntelliSense/IntelliSenseProvider.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ void OnInvalidate(object _unused_)
277277

278278
public void Dispose()
279279
{
280+
Logger.Provider.Info("ExcelDnaIntelliSenseProvider.Dispose");
280281
_loaderNotification.Dispose();
281282
}
282283
}
@@ -481,6 +482,10 @@ void OnInvalidate()
481482

482483
public void Dispose()
483484
{
485+
Logger.Provider.Info("WorkbookIntelliSenseProvider.Dispose");
486+
var xlApp = (Application)ExcelDnaUtil.Application;
487+
xlApp.WorkbookOpen -= Excel_WorkbookOpen;
488+
xlApp.WorkbookBeforeClose -= Excel_WorkbookBeforeClose;
484489
}
485490
}
486491

Source/ExcelDna.IntelliSense/IntelliSenseServer.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,9 @@ public static void Register()
119119
// We don't expect DomainUnload to run when Excel is shutting down.
120120
static void CurrentDomain_DomainUnload(object sender, EventArgs e)
121121
{
122-
// Early shutdown notification
123-
XlCall.ShutdownStarted();
122+
Logger.Initialization.Info("IntelliSenseServer DomainUnload");
123+
//// Early shutdown notification
124+
//XlCall.ShutdownStarted();
124125

125126
UnpublishRegistration();
126127
if (_isActive)
@@ -167,9 +168,10 @@ internal static bool Deactivate()
167168
ClearActiveRegistrationInfo();
168169
return true;
169170
}
170-
catch (Exception /*ex*/)
171+
catch (Exception ex)
171172
{
172173
// TODO: Log
174+
Logger.Initialization.Error($"IntelliSenseServer.Deactivate error: {ex}");
173175
return false;
174176
}
175177
}

Source/ExcelDna.IntelliSense/IntellisenseHelper.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,16 @@ void UpdateDisplay(IIntelliSenseProvider provider)
7070

7171
public void Dispose()
7272
{
73+
Logger.Initialization.Verbose("IntelliSenseHelper Dispose Start");
74+
7375
foreach (var provider in _providers)
7476
{
7577
provider.Dispose();
7678
}
79+
_uiMonitor.Dispose();
7780
_display.Dispose();
81+
82+
Logger.Initialization.Verbose("IntelliSenseHelper Dispose End");
7883
}
7984
}
8085
}

Source/ExcelDna.IntelliSense/LoaderNotification.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public LoaderNotification()
8989
}
9090

9191
// WARNING! LoaderLock danger here
92+
// LoadNotification event handler must be very careful, not load any other managed library etc...
9293
void Notification(Reason notificationReason, IntPtr pNotificationData, IntPtr context)
9394
{
9495
IntPtr pFullDllName = Marshal.ReadIntPtr(pNotificationData, 4);
@@ -112,6 +113,7 @@ protected virtual void Dispose(bool disposing)
112113
}
113114

114115
var status = LdrUnregisterDllNotification(_cookie);
116+
Logger.Initialization.Verbose($"LoaderNotification LdrUnregisterDllNotification Result: {status}");
115117
disposedValue = true;
116118
}
117119
}
@@ -127,7 +129,7 @@ public void Dispose()
127129
{
128130
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
129131
Dispose(true);
130-
GC.SuppressFinalize(this);
132+
GC.SuppressFinalize(this);
131133
}
132134
#endregion
133135

Source/ExcelDna.IntelliSense/UIMonitor/FormulaEditWatcher.cs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,13 @@ void InstallTextChangeMonitor(AutomationElement element)
246246

247247
if (isTextPatternAvailable)
248248
{
249-
Logger.WindowWatcher.Info("FormulaEdit TextPattern adding change handler");
249+
Logger.WindowWatcher.Info("FormulaEdit/InCellEdit TextPattern adding change handler");
250250
Automation.AddAutomationEventHandler(TextPattern.TextChangedEvent, element, TreeScope.Element, TextChanged);
251251
_enableFormulaPolling = false;
252252
}
253253
else
254254
{
255-
Logger.WindowWatcher.Info("FormulaEdit TextPattern not available - enabling polling");
255+
Logger.WindowWatcher.Info("FormulaEdit/InCellEdit TextPattern not available - enabling polling");
256256
_enableFormulaPolling = true; // Has an effect when focus changes
257257
UpdateFormulaPolling();
258258
}
@@ -263,9 +263,15 @@ void UninstallTextChangeMonitor(AutomationElement element)
263263
bool isTextPatternAvailable = (bool)element.GetCurrentPropertyValue(AutomationElement.IsTextPatternAvailableProperty);
264264
if (isTextPatternAvailable)
265265
{
266-
Logger.WindowWatcher.Info("FormulaEdit TextPattern removing change handler");
266+
Logger.WindowWatcher.Info("FormulaEdit/InCellEdit removing text change handler");
267267
Automation.RemoveAutomationEventHandler(TextPattern.TextChangedEvent, element, TextChanged);
268268
}
269+
else
270+
{
271+
Logger.WindowWatcher.Info("FormulaEdit/InCellEdit disabling polling");
272+
_enableFormulaPolling = false;
273+
UpdateFormulaPolling();
274+
}
269275
}
270276

271277
// Breaks the PopupList SelectedItemChange event handler ... !?
@@ -300,13 +306,12 @@ void UpdateFormulaPolling()
300306
}
301307
else // no focus
302308
{
303-
if (_formulaPollingTimer != null)
304-
_formulaPollingTimer.Change(-1, -1);
309+
_formulaPollingTimer?.Change(-1, -1);
305310
}
306311
}
307312
else if (_formulaPollingTimer != null)
308313
{
309-
_formulaPollingTimer.Dispose();
314+
_formulaPollingTimer?.Dispose();
310315
_formulaPollingTimer = null;
311316
}
312317
}
@@ -425,27 +430,27 @@ void OnStateChanged(StateChangeEventArgs stateChangeEventArgs)
425430

426431
public void Dispose()
427432
{
428-
if (_formulaPollingTimer != null)
429-
{
430-
_formulaPollingTimer.Dispose();
431-
}
433+
Logger.WindowWatcher.Verbose("FormulaEdit Disposing");
434+
XlCall.ShutdownStarted();
435+
432436
// Not sure we need this:
433437
_windowWatcher.FormulaBarWindowChanged -= _windowWatcher_FormulaBarWindowChanged;
434438
_windowWatcher.InCellEditWindowChanged -= _windowWatcher_InCellEditWindowChanged;
435439
// _windowWatcher.MainWindowChanged -= _windowWatcher_MainWindowChanged;
436440

437-
_syncContextAuto.Post(delegate
441+
_formulaPollingTimer?.Dispose();
442+
_formulaPollingTimer = null;
443+
444+
_syncContextAuto.Send(delegate
438445
{
439-
Debug.Print("Disposing FormulaEditWatcher");
440-
//Automation.RemoveAutomationFocusChangedEventHandler(FocusChangedEventHandler);
441-
//if (_formulaBar != null)
442-
//{
443-
// Automation.RemoveAutomationEventHandler(TextPattern.TextChangedEvent, _formulaBar, TextChanged);
444-
// _formulaBar = null;
445-
//}
446+
if (_formulaBar != null)
447+
{
448+
UninstallTextChangeMonitor(_formulaBar);
449+
_formulaBar = null;
450+
}
446451
if (_inCellEdit != null)
447452
{
448-
Automation.RemoveAutomationEventHandler(TextPattern.TextChangedEvent, _inCellEdit, TextChanged);
453+
UninstallTextChangeMonitor(_inCellEdit);
449454
_inCellEdit = null;
450455
}
451456
//if (_mainWindow != null)

Source/ExcelDna.IntelliSense/UIMonitor/PopupListWatcher.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ void UpdateSelectedItem()
313313
void UpdateSelectedItem(AutomationElement newSelectedItem)
314314
{
315315
// Debug.Print($"POPUPLISTWATCHER WINDOW CURRENT SELECTION {newSelectedItem}");
316+
317+
// TODO: Sometimes the IsVisble is not updated, but we are visible and the first selection is set
318+
316319
if (!IsVisible || newSelectedItem == null)
317320
{
318321
if (_selectedItem == null &&
@@ -364,7 +367,7 @@ public void Dispose()
364367
_windowWatcher.PopupListWindowChanged -= _windowWatcher_PopupListWindowChanged;
365368
_windowWatcher = null;
366369

367-
_syncContextAuto.Post(delegate
370+
_syncContextAuto.Send(delegate
368371
{
369372
Debug.Print("Disposing PopupListWatcher - In Automation context");
370373
if (_popupList != null)

Source/ExcelDna.IntelliSense/UIMonitor/UIMonitor.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,12 +620,11 @@ void RaiseStateUpdates(object updates)
620620

621621
public void Dispose()
622622
{
623-
624623
if (_syncContextAuto == null)
625624
return;
626625

627626
// Send is not supported on _syncContextAuto
628-
_syncContextAuto.Post(delegate
627+
_syncContextAuto.Send(delegate
629628
{
630629
if (_windowWatcher != null)
631630
{
@@ -646,9 +645,16 @@ public void Dispose()
646645
_popupListWatcher.Dispose();
647646
_popupListWatcher = null;
648647
}
649-
_syncContextAuto.Complete();
650-
_syncContextAuto = null;
651648
}, null);
649+
650+
// Let the above delegate and nested calls run, then clean up.
651+
// (not sure it makes a difference anymore...)
652+
_syncContextAuto.Post(delegate
653+
{
654+
_syncContextAuto.Complete();
655+
_syncContextAuto = null;
656+
}, null);
657+
652658
}
653659
}
654660
}

Source/ExcelDna.IntelliSense/UIMonitor/WinEvents.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,13 @@ protected virtual void Dispose(bool disposing)
143143
{
144144
// TODO: dispose managed state (managed objects).
145145
}
146-
_syncContextAuto.Post(winEventHook =>
146+
_syncContextAuto.Send(winEventHook =>
147147
{
148148
try
149149
{
150150
Logger.WinEvents.Info($"UnhookWinEvent called on thread {Thread.CurrentThread.ManagedThreadId}");
151151
bool result = UnhookWinEvent((IntPtr)winEventHook);
152-
Logger.WinEvents.Info($"UnhookWinEvent result {result}");
152+
Logger.WinEvents.Info($"UnhookWinEvent success? {result}");
153153
}
154154
catch (Exception ex)
155155
{
@@ -161,18 +161,20 @@ protected virtual void Dispose(bool disposing)
161161
}
162162
}
163163

164-
~WinEventHook()
165-
{
166-
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
167-
Dispose(false);
168-
}
164+
// TODO: Does this make any sense?
165+
// We _have_to_ Unhook from the automation thread...
166+
// ~WinEventHook()
167+
//{
168+
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
169+
// Dispose(false);
170+
// }
169171

170172
// This code added to correctly implement the disposable pattern.
171173
public void Dispose()
172174
{
173175
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
174176
Dispose(true);
175-
GC.SuppressFinalize(this);
177+
// GC.SuppressFinalize(this);
176178
}
177179
#endregion
178180
}

0 commit comments

Comments
 (0)