Skip to content

Commit 088ce6b

Browse files
authored
Merge pull request #3644 from MDoerner/ShutdownIssueOneMoreRound
More shutdown tweaks
2 parents 3fd108e + 240d729 commit 088ce6b

File tree

11 files changed

+121
-53
lines changed

11 files changed

+121
-53
lines changed

RetailCoder.VBE/AppMenu.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ private void RemoveMenus()
8787
//The parents further down get disposed of/released as part of the remove chain.
8888
_logger.Trace($"Removing parent menu of top-level menu {menu.GetType()}.");
8989
menu.Parent.Dispose();
90-
menu.Parent.Release(true); //todo: Find a way around this!!!
9190
menu.Parent = null;
9291
}
9392
}

RetailCoder.VBE/Extension.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Rubberduck.Root;
1717
using Rubberduck.Settings;
1818
using Rubberduck.SettingsProvider;
19+
using Rubberduck.UI.Command.MenuItems;
1920
using Rubberduck.VBEditor.Events;
2021
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
2122
using Rubberduck.VBEditor.WindowsApi;
@@ -246,7 +247,11 @@ private void ShutdownAddIn()
246247
VBENativeServices.UnhookEvents();
247248

248249
_logger.Log(LogLevel.Trace, "Broadcasting shutdown...");
249-
User32.EnumChildWindows(_ide.MainWindow.Handle(), EnumCallback, new IntPtr(0));
250+
using (var mainWindow = _ide.MainWindow)
251+
{
252+
var mainWindosHndl = mainWindow.Handle();
253+
UiDispatcher.Invoke(() => User32.EnumChildWindows(mainWindosHndl, EnumCallback, new IntPtr(0)));
254+
}
250255

251256
_logger.Log(LogLevel.Trace, "Releasing dockable hosts...");
252257
Windows.ReleaseDockableHosts();

RetailCoder.VBE/Root/RubberduckIoCInstaller.cs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,7 @@ private static void RegisterParseTreeInspections(IWindsorContainer container, As
257257
private void RegisterRubberduckMenu(IWindsorContainer container)
258258
{
259259
const int windowMenuId = 30009;
260-
var commandBars = _vbe.CommandBars;
261-
var menuBar = commandBars[MenuBar];
262-
var controls = menuBar.Controls;
260+
var controls = MainCommandBarControls(MenuBar);
263261
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, windowMenuId);
264262
var menuItemTypes = RubberduckMenuItems();
265263
RegisterMenu<RubberduckParentMenu>(container, controls, beforeIndex, menuItemTypes);
@@ -296,24 +294,36 @@ private static int FindRubberduckMenuInsertionIndex(ICommandBarControls controls
296294
{
297295
for (var i = 1; i <= controls.Count; i++)
298296
{
299-
var item = controls[i];
300-
if (item.IsBuiltIn && item.Id == beforeId)
297+
using (var item = controls[i])
301298
{
302-
return i;
299+
if (item.IsBuiltIn && item.Id == beforeId)
300+
{
301+
return i;
302+
}
303303
}
304304
}
305305

306306
return controls.Count;
307307
}
308308

309+
private ICommandBarControls MainCommandBarControls(int commandBarIndex)
310+
{
311+
ICommandBarControls controls;
312+
using (var commandBars = _vbe.CommandBars)
313+
{
314+
using (var menuBar = commandBars[commandBarIndex])
315+
{
316+
controls = menuBar.Controls;
317+
}
318+
}
319+
return controls;
320+
}
321+
309322
private void RegisterCodePaneContextMenu(IWindsorContainer container)
310323
{
311324
const int listMembersMenuId = 2529;
312-
var commandBars = _vbe.CommandBars;
313-
var menuBar = commandBars[CodeWindow];
314-
var controls = menuBar.Controls;
315-
var beforeControl = controls.FirstOrDefault(control => control.Id == listMembersMenuId);
316-
var beforeIndex = beforeControl == null ? 1 : beforeControl.Index;
325+
var controls = MainCommandBarControls(CodeWindow);
326+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, listMembersMenuId);
317327
var menuItemTypes = CodePaneContextMenuItems();
318328
RegisterMenu<CodePaneContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
319329
}
@@ -333,11 +343,8 @@ private static Type[] CodePaneContextMenuItems()
333343
private void RegisterFormDesignerContextMenu(IWindsorContainer container)
334344
{
335345
const int viewCodeMenuId = 2558;
336-
var commandBars = _vbe.CommandBars;
337-
var menuBar = commandBars[MsForms];
338-
var controls = menuBar.Controls;
339-
var beforeControl = controls.FirstOrDefault(control => control.Id == viewCodeMenuId);
340-
var beforeIndex = beforeControl?.Index ?? 1;
346+
var controls = MainCommandBarControls(MsForms);
347+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, viewCodeMenuId);
341348
var menuItemTypes = FormDesignerContextMenuItems();
342349
RegisterMenu<FormDesignerContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
343350
}
@@ -354,23 +361,17 @@ private static Type[] FormDesignerContextMenuItems()
354361
private void RegisterFormDesignerControlContextMenu(IWindsorContainer container)
355362
{
356363
const int viewCodeMenuId = 2558;
357-
var commandBars = _vbe.CommandBars;
358-
var menuBar = commandBars[MsFormsControl];
359-
var controls = menuBar.Controls;
360-
var beforeControl = controls.FirstOrDefault(control => control.Id == viewCodeMenuId);
361-
var beforeIndex = beforeControl?.Index ?? 1;
364+
var controls = MainCommandBarControls(MsFormsControl);
365+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, viewCodeMenuId);
362366
var menuItemTypes = FormDesignerContextMenuItems();
363367
RegisterMenu<FormDesignerControlContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
364368
}
365369

366370
private void RegisterProjectExplorerContextMenu(IWindsorContainer container)
367371
{
368372
const int projectPropertiesMenuId = 2578;
369-
var commandBars = _vbe.CommandBars;
370-
var menuBar = commandBars[ProjectWindow];
371-
var controls = menuBar.Controls;
372-
var beforeControl = controls.FirstOrDefault(control => control.Id == projectPropertiesMenuId);
373-
var beforeIndex = beforeControl?.Index ?? 1;
373+
var controls = MainCommandBarControls(ProjectWindow);
374+
var beforeIndex = FindRubberduckMenuInsertionIndex(controls, projectPropertiesMenuId);
374375
var menuItemTypes = ProjectWindowContextMenuItems();
375376
RegisterMenu<ProjectWindowContextParentMenu>(container, controls, beforeIndex, menuItemTypes);
376377
}

RetailCoder.VBE/UI/Command/MenuItems/CommandBars/AppCommandBarBase.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@ private ICommandBarControl InitializeChildControl(ICommandMenuItem item)
114114
return null;
115115
}
116116

117-
var child = CommandBarButtonFactory.Create(Item.Controls);
117+
ICommandBarButton child;
118+
using (var controls = Item.Controls)
119+
{
120+
child = CommandBarButtonFactory.Create(controls);
121+
}
118122
child.Style = item.ButtonStyle;
119123
child.Picture = item.Image;
120124
child.Mask = item.Mask;

RetailCoder.VBE/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ private void RemoveChildren()
101101
foreach (var child in _items.Keys.Select(item => item as IParentMenuItem).Where(child => child != null))
102102
{
103103
child.RemoveMenu();
104+
child.Parent.Dispose();
104105
}
105106
foreach (var child in _items.Values.Select(item => item as ICommandBarButton).Where(child => child != null))
106107
{
@@ -155,7 +156,11 @@ private ICommandBarControl InitializeChildControl(ICommandMenuItem item)
155156
return null;
156157
}
157158

158-
var child = CommandBarButtonFactory.Create(Item.Controls);
159+
ICommandBarButton child;
160+
using (var controls = Item.Controls)
161+
{
162+
child = CommandBarButtonFactory.Create(controls);
163+
}
159164
child.Picture = item.Image;
160165
child.Mask = item.Mask;
161166
child.ApplyIcon();

RetailCoder.VBE/UI/Controls/SearchResultPresenterInstanceManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ private void Dispose(bool disposing)
5454
{
5555
_view.ViewModel.LastTabClosed -= viewModel_LastTabClosed;
5656
}
57+
_presenter?.Dispose();
58+
5759
_disposed = true;
5860
}
5961
}

RetailCoder.VBE/UI/DockableToolwindowPresenter.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ private IWindow CreateToolWindow(IDockableUserControl control)
5050
IWindow toolWindow;
5151
try
5252
{
53-
var info = _vbe.Windows.CreateToolWindow(_addin, _DockableWindowHost.RegisteredProgId, control.Caption, control.ClassId);
54-
_userControlObject = info.UserControl;
55-
toolWindow = info.ToolWindow;
53+
using (var windows = _vbe.Windows)
54+
{
55+
var info = windows.CreateToolWindow(_addin, _DockableWindowHost.RegisteredProgId, control.Caption, control.ClassId);
56+
_userControlObject = info.UserControl;
57+
toolWindow = info.ToolWindow;
58+
}
5659
}
5760
catch (COMException exception)
5861
{
@@ -120,7 +123,7 @@ public void Dispose()
120123
~DockableToolwindowPresenter()
121124
{
122125
// destructor for tracking purposes only - do not suppress unless
123-
Debug.WriteLine("DockableToolwindowPresenter finalized.");
126+
Debug.WriteLine($"DockableToolwindowPresenter of type {this.GetType()} finalized.");
124127
}
125128
}
126129
}

RetailCoder.VBE/UI/DockableWindowHost.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ protected override bool ProcessKeyPreview(ref Message m)
142142
protected override void DefWndProc(ref Message m)
143143
{
144144
//See the comment in the ctor for why we have to listen for this.
145-
if (m.Msg == (int) WM.DESTROY)
145+
if (m.Msg == (int) WM.DESTROY && !_released)
146146
{
147147
Debug.WriteLine("DockableWindowHost received WM.DESTROY.");
148148
try
@@ -162,10 +162,19 @@ protected override void DefWndProc(ref Message m)
162162

163163
//override
164164

165+
private bool _released;
165166
public void Release()
166167
{
168+
if (_released)
169+
{
170+
return;
171+
}
172+
167173
Debug.WriteLine("DockableWindowHost release called.");
168174
_subClassingWindow.Dispose();
175+
_thisHandle.Free();
176+
177+
_released = true;
169178
}
170179

171180
protected override void DestroyHandle()
@@ -218,6 +227,20 @@ public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr
218227
}
219228
return base.SubClassProc(hWnd, msg, wParam, lParam, uIdSubclass, dwRefData);
220229
}
230+
231+
private bool _disposed;
232+
protected override void Dispose(bool disposing)
233+
{
234+
if (!_disposed && disposing && !_closing)
235+
{
236+
OnCallBackEvent(new SubClassingWindowEventArgs(IntPtr.Zero) { Closing = true });
237+
_closing = true;
238+
}
239+
240+
_disposed = true;
241+
242+
base.Dispose(disposing);
243+
}
221244
}
222245
}
223246
}

Rubberduck.VBEEditor/SafeComWrappers/SafeComWrapper.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,17 @@ public void Release(bool final = false)
5454
else
5555
{
5656
_rcwReferenceCount = Marshal.ReleaseComObject(Target);
57-
_logger.Trace($"Released COM wrapper of type {this.GetType()} with remaining reference count {_rcwReferenceCount}.");
57+
if (_rcwReferenceCount >= 0)
58+
{
59+
_logger.Trace($"Released COM wrapper of type {this.GetType()} with remaining reference count {_rcwReferenceCount}.");
60+
}
61+
else
62+
{
63+
_logger.Warn($"Released COM wrapper of type {this.GetType()} whose underlying RCW has already been released from outside the SafeComWrapper.");
64+
}
5865
}
66+
67+
5968
}
6069
catch(COMException exception)
6170
{
@@ -73,7 +82,7 @@ public void Release(bool final = false)
7382
}
7483
}
7584

76-
public bool HasBeenReleased => _rcwReferenceCount == 0;
85+
public bool HasBeenReleased => _rcwReferenceCount <= 0;
7786

7887
public bool IsWrappingNullReference => Target == null;
7988
object INullObjectWrapper.Target => Target;

Rubberduck.VBEEditor/SafeComWrappers/VBA/Windows.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System.Collections;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Runtime.InteropServices;
5+
using Microsoft.Office.Interop.Outlook;
36
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
47
using VB = Microsoft.Vbe.Interop;
58

@@ -40,6 +43,7 @@ public static void ReleaseDockableHosts()
4043
dynamic host = item.Value;
4144
host.Release();
4245
}
46+
_dockableHosts.Clear();
4347
}
4448

4549
IEnumerator IEnumerable.GetEnumerator()

0 commit comments

Comments
 (0)