Skip to content

Commit 3fd108e

Browse files
authored
Merge pull request #3635 from MDoerner/ShutdownIssueNextRound
More COM release on shutdown
2 parents de375de + ae460ec commit 3fd108e

File tree

7 files changed

+85
-13
lines changed

7 files changed

+85
-13
lines changed

RetailCoder.VBE/AppMenu.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading;
5+
using NLog;
46
using Rubberduck.Parsing;
57
using Rubberduck.Parsing.VBA;
68
using Rubberduck.UI;
@@ -17,6 +19,8 @@ public class AppMenu : IAppMenu, IDisposable
1719
private readonly ISelectionChangeService _selectionService;
1820
private readonly RubberduckCommandBar _stateBar;
1921

22+
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
23+
2024
public AppMenu(IEnumerable<IParentMenuItem> menus, IParseCoordinator parser, ISelectionChangeService selectionService, RubberduckCommandBar stateBar)
2125
{
2226
_menus = menus.ToList();
@@ -77,7 +81,14 @@ private void RemoveMenus()
7781
{
7882
foreach (var menu in _menus.Where(menu => menu.Item != null))
7983
{
84+
_logger.Debug($"Starting removal of top-level menu {menu.GetType()}.");
8085
menu.RemoveMenu();
86+
//We do this here and not in the menu items because we only want to dispose of/release the parents of the top level parent menus.
87+
//The parents further down get disposed of/released as part of the remove chain.
88+
_logger.Trace($"Removing parent menu of top-level menu {menu.GetType()}.");
89+
menu.Parent.Dispose();
90+
menu.Parent.Release(true); //todo: Find a way around this!!!
91+
menu.Parent = null;
8192
}
8293
}
8394
}

RetailCoder.VBE/Extension.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,20 @@ private void ShutdownAddIn()
265265
_container = null;
266266
}
267267

268+
if (_addin != null)
269+
{
270+
_logger.Log(LogLevel.Trace, "Disposing AddIn wrapper...");
271+
_addin.Dispose();
272+
_addin = null;
273+
}
274+
275+
if (_ide != null)
276+
{
277+
_logger.Log(LogLevel.Trace, "Disposing VBE wrapper...");
278+
_ide.Dispose();
279+
_ide = null;
280+
}
281+
268282
_isInitialized = false;
269283
_logger.Log(LogLevel.Info, "No exceptions were thrown.");
270284
}

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,16 @@ public void RemoveCommandBar()
170170
{
171171
try
172172
{
173-
Logger.Debug("Removing commandbar.");
174-
RemoveChildren();
175-
Item?.Delete();
176-
Item?.Release();
177-
Item = null;
178-
Parent = null;
173+
if (Item != null)
174+
{
175+
Logger.Debug("Removing commandbar.");
176+
RemoveChildren();
177+
Item.Delete();
178+
Item.Dispose();
179+
Item = null;
180+
Parent?.Dispose();
181+
Parent = null;
182+
}
179183
}
180184
catch (COMException exception)
181185
{
@@ -199,7 +203,7 @@ private void RemoveChildren()
199203
button.Click -= child_Click;
200204
}
201205
button.Delete();
202-
button.Release();
206+
button.Dispose();
203207
}
204208
}
205209
catch (COMException exception)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public void RemoveMenu()
9292
Logger.Debug($"Removing menu {_key}.");
9393
RemoveChildren();
9494
Item?.Delete();
95-
Item?.Release();
95+
Item?.Dispose();
9696
Item = null;
9797
}
9898

@@ -106,7 +106,7 @@ private void RemoveChildren()
106106
{
107107
child.Click -= child_Click;
108108
child.Delete();
109-
child.Release();
109+
child.Dispose();
110110
}
111111
}
112112

RetailCoder.VBE/UI/DockableToolwindowPresenter.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public interface IDockablePresenter : IPresenter
2020
UserControl UserControl { get; }
2121
}
2222

23-
public abstract class DockableToolwindowPresenter : IDockablePresenter
23+
public abstract class DockableToolwindowPresenter : IDockablePresenter, IDisposable
2424
{
2525
private readonly IAddIn _addin;
2626
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@@ -100,6 +100,23 @@ private void EnsureMinimumWindowSize(IWindow window)
100100
public virtual void Show() => _window.IsVisible = true;
101101
public virtual void Hide() => _window.IsVisible = false;
102102

103+
104+
private bool _isDisposed;
105+
public void Dispose()
106+
{
107+
if (_isDisposed)
108+
{
109+
return;
110+
}
111+
112+
Logger.Trace($"Disposing DockableWindowPresenter of type {this.GetType()}.");
113+
114+
_window.Dispose();
115+
116+
_isDisposed = true;
117+
}
118+
119+
103120
~DockableToolwindowPresenter()
104121
{
105122
// destructor for tracking purposes only - do not suppress unless

Rubberduck.VBEEditor/SafeComWrappers/Abstract/ISafeComWrapper.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using System;
2+
13
namespace Rubberduck.VBEditor.SafeComWrappers.Abstract
24
{
3-
public interface ISafeComWrapper : INullObjectWrapper
5+
public interface ISafeComWrapper : INullObjectWrapper, IDisposable
46
{
57
void Release(bool final = false);
68
bool HasBeenReleased { get; }

Rubberduck.VBEEditor/SafeComWrappers/SafeComWrapper.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Runtime.InteropServices;
23
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
34
using NLog;
@@ -15,7 +16,7 @@ protected SafeComWrapper(T target)
1516
}
1617

1718
private int? _rcwReferenceCount;
18-
public virtual void Release(bool final = false)
19+
public void Release(bool final = false)
1920
{
2021
if (HasBeenReleased)
2122
{
@@ -103,5 +104,28 @@ public override bool Equals(object obj)
103104
{
104105
return !(a == b);
105106
}
106-
}
107+
108+
109+
public void Dispose()
110+
{
111+
Dispose(true);
112+
GC.SuppressFinalize(this);
113+
}
114+
115+
private bool _isDisposed;
116+
protected virtual void Dispose(bool disposing)
117+
{
118+
if (_isDisposed)
119+
{
120+
return;
121+
}
122+
123+
if (disposing && !HasBeenReleased)
124+
{
125+
Release();
126+
}
127+
128+
_isDisposed = true;
129+
}
130+
}
107131
}

0 commit comments

Comments
 (0)