What is the correct way to subscribe to the EnvDTE

2019-02-21 03:12发布

问题:

I'm porting an VS addin to a VS Package. The package subscribes to OnBuildBegin and OnPublishBegin when the package is initialized. Visual Studio triggers OnBuildBegin as expected, but OnPublishBegin is never called.

More or less the same code work in Visual Studio 2013, 2012, and 2010 as an addin. But in VS 2015 as a VS Package, OnPublishBegin doesn't appear to be functional.

Sample Code is below.

To test the code running the debugger configured to start a second instance of VS in Experiment Mode. In the second instance, I open a different solution and publish using the Publish Wizard.

using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace MyPackage
{
    [PackageRegistration(UseManagedResourcesOnly = true)]
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About
    [Guid(VSPackage.PackageGuidString)]
    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
    [ProvideAutoLoad(UIContextGuids80.SolutionBuilding)]
    public sealed class VSPackage : Package
    {
        public const string PackageGuidString = "a8ddf848-00ea-4e4e-b11a-65663a8a8021";

        private DTE2 application;
        public VSPackage()
        {
        }

        protected override void Initialize()
        {
            base.Initialize();
            this.application = (DTE2) this.GetService(typeof(DTE));

            ((Events2)this.application.Events).BuildEvents.OnBuildBegin += this.OnBuildBegin;
            ((Events2)this.application.Events).PublishEvents.OnPublishBegin += this.OnPublishBegin;
        }

        private void OnBuildBegin(vsBuildScope scope, vsBuildAction action)
        {
            MessageBox.Show("OnBuildBegin");
        }

        private void OnPublishBegin(ref bool pubContinue)
        {
            MessageBox.Show("OnPublishBegin");
        }
    }
}

Can anyone shed light on the problem for me?

回答1:

It is highly recommended to keep references to Events objects to protect them from GC:

protected override void Initialize()
{
    events = application.Events;
    buildEvents = events.BuildEvents;
    publishEvents = events.PublishEvents;
    buildEvents.OnBuildBegin += this.OnBuildBegin;
    publishEvents.OnPublishBegin += this.OnPublishBegin;
}

private Events2 events;
private BuildEvents buildEvents;
private PublishEvents publishEvents;