diff --git a/IncludeToolbox/TrialAndErrorRemoval.cs b/IncludeToolbox/TrialAndErrorRemoval.cs index 585f670..5d73148 100644 --- a/IncludeToolbox/TrialAndErrorRemoval.cs +++ b/IncludeToolbox/TrialAndErrorRemoval.cs @@ -25,6 +25,11 @@ internal sealed class TrialAndErrorRemoval private AutoResetEvent outputWaitEvent = new AutoResetEvent(false); private const int timeoutMS = 30000; // 30 seconds + /// + /// Need to keep build events object around as long as it is used, otherwise the events may not be fired! + /// + private BuildEvents buildEvents; + public void PerformTrialAndErrorIncludeRemoval(EnvDTE.Document document, TrialAndErrorRemovalOptionsPage settings) { if (document == null) @@ -64,8 +69,7 @@ public void PerformTrialAndErrorIncludeRemoval(EnvDTE.Document document, TrialAn } // Hook into build events. - document.DTE.Events.BuildEvents.OnBuildProjConfigDone += OnBuildConfigFinished; - document.DTE.Events.BuildEvents.OnBuildDone += OnBuildFinished; + SubscribeBuildEvents(); // The rest runs in a separate thread since the compile function is non blocking and we want to use BuildEvents // We are not using Task, since we want to make use of WaitHandles - using this together with Task is a bit more complicated to get right. @@ -115,7 +119,6 @@ private void ExtractSelectionAndIncludes(EnvDTE.Document document, TrialAndError string documentText = documentTextView.TextView.TextSnapshot.GetText(); IEnumerable includeLines = Formatter.IncludeLineInfo.ParseIncludes(documentText, Formatter.ParseOptions.IgnoreIncludesInPreprocessorConditionals | Formatter.ParseOptions.KeepOnlyValidIncludes); - // Optionally skip top most include. if (settings.IgnoreFirstInclude) includeLines = includeLines.Skip(1); @@ -249,8 +252,7 @@ private void OnTrialAndErrorRemovalDone(IVsThreadedWaitDialog2 progressDialog, E progressDialog.EndWaitDialog(); // Remove build hook again. - document.DTE.Events.BuildEvents.OnBuildDone -= OnBuildFinished; - document.DTE.Events.BuildEvents.OnBuildProjConfigDone -= OnBuildConfigFinished; + UnsubscribeBuildEvents(); // Message. Output.Instance.WriteLine("Removed {0} #include directives from '{1}'", numRemovedIncludes, document.Name); @@ -261,6 +263,20 @@ private void OnTrialAndErrorRemovalDone(IVsThreadedWaitDialog2 progressDialog, E OnFileFinished?.Invoke(numRemovedIncludes, canceled); } + private void SubscribeBuildEvents() + { + buildEvents = VSUtils.GetDTE().Events.BuildEvents; + buildEvents.OnBuildDone += OnBuildFinished; + buildEvents.OnBuildProjConfigDone += OnBuildConfigFinished; + } + + private void UnsubscribeBuildEvents() + { + buildEvents.OnBuildDone -= OnBuildFinished; + buildEvents.OnBuildProjConfigDone -= OnBuildConfigFinished; + buildEvents = null; + } + private void OnBuildFinished(vsBuildScope scope, vsBuildAction action) { //Output.Instance.WriteLine("OnBuildFinished. scope: {0}, action: {1}", scope, action);