Skip to content

Commit b817344

Browse files
authored
Merge pull request #3653 from MDoerner/ShutdownIssueAnotherRound
More COM release and Shutdown tweaks
2 parents 6d0bc01 + a687742 commit b817344

File tree

25 files changed

+393
-177
lines changed

25 files changed

+393
-177
lines changed

RetailCoder.VBE/Common/RubberduckHooks.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr
147147
break;
148148
case WM.CLOSE:
149149
case WM.DESTROY:
150-
case WM.RUBBERDUCK_SINKING:
151150
Detach();
152151
break;
153152
}
@@ -172,5 +171,14 @@ private bool HandleHotkeyMessage(IntPtr wParam)
172171
}
173172
return processed;
174173
}
174+
175+
protected override void Dispose(bool disposing)
176+
{
177+
if (disposing)
178+
{
179+
Detach();
180+
}
181+
base.Dispose(disposing);
182+
}
175183
}
176184
}

RetailCoder.VBE/Extension.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@
1616
using Rubberduck.Root;
1717
using Rubberduck.Settings;
1818
using Rubberduck.SettingsProvider;
19-
using Rubberduck.UI.Command.MenuItems;
2019
using Rubberduck.VBEditor.Events;
2120
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
22-
using Rubberduck.VBEditor.WindowsApi;
23-
using User32 = Rubberduck.Common.WinAPI.User32;
2421
using Windows = Rubberduck.VBEditor.SafeComWrappers.VBA.Windows;
2522

2623
namespace Rubberduck
@@ -76,6 +73,7 @@ public void OnConnection(object Application, ext_ConnectMode ConnectMode, object
7673
// normal execution path - don't initialize just yet, wait for OnStartupComplete to be called by the host.
7774
break;
7875
case ext_ConnectMode.ext_cm_AfterStartup:
76+
_isBeginShutdownExecuted = false; //When we reconnect after having been unloaded, the variable might no longer have its initial value.
7977
InitializeAddIn();
8078
break;
8179
}
@@ -246,13 +244,6 @@ private void ShutdownAddIn()
246244
_logger.Log(LogLevel.Trace, "Unhooking VBENativeServices events...");
247245
VBENativeServices.UnhookEvents();
248246

249-
_logger.Log(LogLevel.Trace, "Broadcasting shutdown...");
250-
using (var mainWindow = _ide.MainWindow)
251-
{
252-
var mainWindosHndl = mainWindow.Handle();
253-
UiDispatcher.Invoke(() => User32.EnumChildWindows(mainWindosHndl, EnumCallback, new IntPtr(0)));
254-
}
255-
256247
_logger.Log(LogLevel.Trace, "Releasing dockable hosts...");
257248
Windows.ReleaseDockableHosts();
258249

@@ -306,11 +297,5 @@ private void ShutdownAddIn()
306297
_isInitialized = false;
307298
}
308299
}
309-
310-
private static int EnumCallback(IntPtr hwnd, IntPtr lparam)
311-
{
312-
User32.SendMessage(hwnd, WM.RUBBERDUCK_SINKING, IntPtr.Zero, IntPtr.Zero);
313-
return 1;
314-
}
315300
}
316301
}

RetailCoder.VBE/Navigation/RegexSearchReplace/RegexSearchReplace.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,27 @@ private List<RegexSearchResult> SearchCurrentProject(string searchPattern)
167167
private List<RegexSearchResult> SearchOpenProjects(string searchPattern)
168168
{
169169
var results = new List<RegexSearchResult>();
170-
var projects = _vbe.VBProjects;
170+
using (var projects = _vbe.VBProjects)
171171
{
172-
var modules = projects
173-
.Where(project => project.Protection == ProjectProtection.Unprotected)
174-
.SelectMany(project => project.VBComponents)
175-
.Select(component => component.CodeModule);
176-
177-
foreach (var module in modules)
172+
foreach (var project in projects)
178173
{
179-
results.AddRange(GetResultsFromModule(module, searchPattern));
174+
if (project.Protection == ProjectProtection.Locked)
175+
{
176+
project.Dispose();
177+
continue;
178+
}
179+
using (var components = project.VBComponents)
180+
{
181+
foreach (var component in components)
182+
{
183+
using (var codeModule = component.CodeModule)
184+
{
185+
results.AddRange(GetResultsFromModule(codeModule, searchPattern));
186+
}
187+
component.Dispose();
188+
}
189+
}
190+
project.Dispose();
180191
}
181192

182193
return results;

RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,15 +451,31 @@ private void RenameModule()
451451
private void RenameProject()
452452
{
453453
RequestParseAfterRename = false;
454-
var projects = _model.VBE.VBProjects;
455-
var project = projects.SingleOrDefault(p => p.ProjectId == _model.Target.ProjectId);
454+
var project = ProjectById(_vbe, _model.Target.ProjectId);
456455

457456
if (project != null)
458457
{
459458
project.Name = _model.NewName;
459+
project.Dispose();
460460
}
461461
}
462462

463+
private IVBProject ProjectById(IVBE vbe, string projectId)
464+
{
465+
using (var projects = vbe.VBProjects)
466+
{
467+
foreach (var project in projects)
468+
{
469+
if (project.ProjectId == projectId)
470+
{
471+
return project;
472+
}
473+
project.Dispose();
474+
}
475+
}
476+
return null;
477+
}
478+
463479
private void RenameDefinedFormatMembers(IEnumerable<Declaration> members, string underscoreFormat)
464480
{
465481
if (!members.Any()) { return; }

RetailCoder.VBE/UI/CodeExplorer/Commands/AddComponentCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public bool CanAddComponent(CodeExplorerItemViewModel parameter)
2020
{
2121
try
2222
{
23-
return GetDeclaration(parameter) != null || _vbe.VBProjects.Count == 1;
23+
return GetDeclaration(parameter) != null || _vbe.ProjectsCount == 1;
2424
}
2525
catch (COMException)
2626
{

RetailCoder.VBE/UI/CodeExplorer/Commands/AddTestModuleCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ protected override bool EvaluateCanExecute(object parameter)
2323
{
2424
try
2525
{
26-
return GetDeclaration(parameter) != null || _vbe.VBProjects.Count == 1;
26+
return GetDeclaration(parameter) != null || _vbe.ProjectsCount == 1;
2727
}
2828
catch (COMException)
2929
{

RetailCoder.VBE/UI/CodeExplorer/Commands/ImportCommand.cs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,70 @@ public ImportCommand(IVBE vbe, IOpenFileDialog openFileDialog) : base(LogManager
3131

3232
protected override bool EvaluateCanExecute(object parameter)
3333
{
34-
return parameter != null || _vbe.VBProjects.Count == 1 || _vbe.ActiveVBProject != null;
34+
return parameter != null || _vbe.ProjectsCount == 1 || ThereIsAValidActiveProject();
35+
}
36+
37+
private bool ThereIsAValidActiveProject()
38+
{
39+
using (var activeProject = _vbe.ActiveVBProject)
40+
{
41+
return activeProject != null;
42+
}
3543
}
3644

3745
protected override void OnExecute(object parameter)
3846
{
39-
var project = GetNodeProject(parameter as CodeExplorerItemViewModel) ?? _vbe.ActiveVBProject;
47+
var usingFreshProjectWrapper = false;
48+
49+
var project = GetNodeProject(parameter as CodeExplorerItemViewModel);
4050

4151
if (project == null)
4252
{
43-
if (_vbe.VBProjects.Count == 1)
53+
if (_vbe.ProjectsCount == 1)
4454
{
45-
project = _vbe.VBProjects[1];
55+
usingFreshProjectWrapper = true;
56+
using (var projects = _vbe.VBProjects)
57+
{
58+
project = projects[1];
59+
}
4660
}
47-
else if (_vbe.ActiveVBProject != null)
61+
else if (ThereIsAValidActiveProject())
4862
{
63+
usingFreshProjectWrapper = true;
4964
project = _vbe.ActiveVBProject;
5065
}
5166
}
5267

5368
if (project == null || _openFileDialog.ShowDialog() != DialogResult.OK)
5469
{
70+
if (usingFreshProjectWrapper)
71+
{
72+
project?.Dispose();
73+
}
5574
return;
5675
}
5776

5877
var fileExts = _openFileDialog.FileNames.Select(s => s.Split('.').Last());
5978
if (fileExts.Any(fileExt => !new[] {"bas", "cls", "frm"}.Contains(fileExt)))
6079
{
80+
if (usingFreshProjectWrapper)
81+
{
82+
project.Dispose();
83+
}
6184
return;
6285
}
6386

6487
foreach (var filename in _openFileDialog.FileNames)
6588
{
66-
project.VBComponents.Import(filename);
89+
using (var components = project.VBComponents)
90+
{
91+
components.Import(filename);
92+
}
93+
}
94+
95+
if (usingFreshProjectWrapper)
96+
{
97+
project.Dispose();
6798
}
6899
}
69100

RetailCoder.VBE/UI/CodeExplorer/Commands/OpenProjectPropertiesCommand.cs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Rubberduck.Navigation.CodeExplorer;
44
using Rubberduck.UI.Command;
55
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
6+
using Rubberduck.VBEditor.SafeComWrappers.Office.Core.Abstract;
67

78
namespace Rubberduck.UI.CodeExplorer.Commands
89
{
@@ -20,10 +21,7 @@ protected override bool EvaluateCanExecute(object parameter)
2021
{
2122
try
2223
{
23-
var projects = _vbe.VBProjects;
24-
{
25-
return parameter != null || projects.Count == 1;
26-
}
24+
return parameter != null || _vbe.ProjectsCount == 1;
2725
}
2826
catch (COMException)
2927
{
@@ -35,34 +33,34 @@ protected override void OnExecute(object parameter)
3533
{
3634
const int openProjectPropertiesId = 2578;
3735

38-
var projects = _vbe.VBProjects;
36+
using (var commandBars = _vbe.CommandBars)
3937
{
40-
var commandBars = _vbe.CommandBars;
41-
var command = commandBars.FindControl(openProjectPropertiesId);
42-
43-
if (projects.Count == 1)
38+
using (var command = commandBars.FindControl(openProjectPropertiesId))
4439
{
45-
command.Execute();
46-
return;
47-
}
40+
if (_vbe.ProjectsCount == 1)
41+
{
42+
command.Execute();
43+
return;
44+
}
4845

49-
var node = parameter as CodeExplorerItemViewModel;
50-
while (!(node is ICodeExplorerDeclarationViewModel))
51-
{
52-
// ReSharper disable once PossibleNullReferenceException
53-
node = node.Parent; // the project node is an ICodeExplorerDeclarationViewModel--no worries here
54-
}
46+
var node = parameter as CodeExplorerItemViewModel;
47+
while (!(node is ICodeExplorerDeclarationViewModel))
48+
{
49+
// ReSharper disable once PossibleNullReferenceException
50+
node = node.Parent; // the project node is an ICodeExplorerDeclarationViewModel--no worries here
51+
}
5552

56-
try
57-
{
58-
_vbe.ActiveVBProject = node.GetSelectedDeclaration().Project;
59-
}
60-
catch (COMException)
61-
{
62-
return; // the project was probably removed from the VBE, but not from the CE
63-
}
53+
try
54+
{
55+
_vbe.ActiveVBProject = node.GetSelectedDeclaration().Project;
56+
}
57+
catch (COMException)
58+
{
59+
return; // the project was probably removed from the VBE, but not from the CE
60+
}
6461

65-
command.Execute();
62+
command.Execute();
63+
}
6664
}
6765
}
6866
}

RetailCoder.VBE/UI/Command/AddTestModuleCommand.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,17 @@ private string DeclarationFormatFor(string declarationFormat, string type, IUnit
119119

120120
private IVBProject GetProject()
121121
{
122-
var activeProject = _vbe.ActiveVBProject;
123-
if (!activeProject.IsWrappingNullReference)
122+
using (var activeProject = _vbe.ActiveVBProject)
124123
{
125-
return activeProject;
124+
if (!activeProject.IsWrappingNullReference)
125+
{
126+
return activeProject;
127+
}
126128
}
127129

128-
var projects = _vbe.VBProjects;
130+
using (var projects = _vbe.VBProjects)
129131
{
130-
return projects.Count == 1
132+
return projects.Count == 1
131133
? projects[1]
132134
: new VBProject(null);
133135
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ private ICommandBarControl InitializeChildControl(ICommandMenuItem item)
166166
child.ApplyIcon();
167167

168168
child.BeginsGroup = item.BeginGroup;
169-
child.Tag = $"{Item.Parent.Name}::{Item.Tag}::{item.GetType().Name}";
169+
using (var itemParent = Item.Parent)
170+
{
171+
child.Tag = $"{itemParent.Name}::{Item.Tag}::{item.GetType().Name}";
172+
}
170173
child.Caption = item.Caption.Invoke();
171174
var command = item.Command; // todo: add 'ShortcutText' to a new 'interface CommandBase : System.Windows.Input.CommandBase'
172175
child.ShortcutText = command != null

0 commit comments

Comments
 (0)