【问题标题】:How to get notification when a successful build has finished?成功构建完成后如何获得通知?
【发布时间】:2010-05-10 10:44:44
【问题描述】:

我正在编写一个 VS 插件,我需要在构建成功后运行某个方法。 我尝试过使用dte.Events.BuildEvents.OnBuildDone,但即使构建失败也会发生该事件。

是否有我应该使用的属性或其他事件?

【问题讨论】:

    标签: visual-studio build add-in envdte


    【解决方案1】:

    OnBuildDone 事件无法告诉您发生了什么。解决方案中的某些项目可能已正确构建,而有些则没有。您将需要 OnBuildProjConfigDone 代替。为每个项目触发,Success 参数告诉你它是否有效。

    【讨论】:

    • 在我的情况下 OnBuildDone 从未触发,但 OnBuildProjConfigDone 工作正常
    • @DinisCruz 如果您不持有对 dte.Events.BuildEvents 的引用,有时 OnBuildDone 不会触发
    • 这里有一个完整的代码示例:github.com/edsykes/VisualStudioBuildEvents
    【解决方案2】:

    通常,您需要处理正在构建的多个项目。这可能是一个解决方案构建,或者构建一个依赖于另一个项目的项目。

    因此,要确定成功构建何时完成,您需要结合使用两个构建事件:

    OnBuildProjConfigDone 和 OnBuildDone。

    您还需要一个成员变量来跟踪整体构建状态。

    将为每个构建的项目调用 OnBuildProjConfigDone 处理程序,并传递一个布尔值来告诉您该项目构建是否成功。将此结果分配给您的成员变量以跟踪整体状态。

    最后,您的 OnBuildDone 处理程序将被调用。在这里,您可以查看您的成员变量以查看是否有任何项目构建失败。

    这是我为 VS2012 编写的扩展中的一些示例代码。该扩展提供了一个“自定义构建”命令,用于构建活动项目并在构建成功时启动调试器。

    private bool _overallBuildSuccess;
    private bool _customBuildInProgress;
    
    private void CustomBuild_MenuItemCallback(object sender, EventArgs e)
    {
        // Listen to the necessary build events.
        DTE2 dte = (DTE2)GetGlobalService(typeof(SDTE));
        dte.Events.BuildEvents.OnBuildDone += BuildEvents_OnBuildDone;
        dte.Events.BuildEvents.OnBuildProjConfigDone += BuildEvents_OnBuildProjConfigDone;
    
        try
        {
            // Build the active project.
            _customBuildInProgress = true;
            dte.ExecuteCommand("Build.BuildSelection");
        }
        catch (COMException)
        {
            _customBuildInProgress = false;
            WriteToOutputWindow("Build", "Could not determine project to build from selection");
        }
    }
    
    private void BuildEvents_OnBuildProjConfigDone(string project, string projectConfig, string platform, string solutionConfig, bool success)
    {
        // Ignore this build event if we didn't start it.
        if (!_customBuildInProgress)
        {
            return;
        }
    
        // Keep track of the overall build success.
        _overallBuildSuccess = success;
    }
    
    private void BuildEvents_OnBuildDone(EnvDTE.vsBuildScope scope, EnvDTE.vsBuildAction action)
    {
        // Ignore this build event if we didn't start it.
        if (!_customBuildInProgress)
        {
            return;
        }
    
        _customBuildInProgress = false;
    
        if (_overallBuildSuccess)
        {
            // Launch the debugger.
            DTE2 dte = (DTE2)GetGlobalService(typeof(SDTE));
            dte.ExecuteCommand("Debug.Start");
        }
        else
        {
            WriteToOutputWindow("Build", "Custom build failed.");
        }
    }
    
    private void WriteToOutputWindow(string paneName, string message)
    {
        DTE2 dte = (DTE2)GetGlobalService(typeof(SDTE));
    
        Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
        OutputWindow outputWindow = (OutputWindow)window.Object;
    
        OutputWindowPane targetPane = outputWindow.OutputWindowPanes.Cast<OutputWindowPane>()
            .FirstOrDefault(x => x.Name.ToLower() == paneName.ToLower());
    
        if (targetPane == null)
        {
            targetPane = outputWindow.OutputWindowPanes.Add(paneName);
        }
    
        targetPane.Activate();
        outputWindow.ActivePane.OutputString(message);
        outputWindow.ActivePane.OutputString(Environment.NewLine);
    }
    

    【讨论】:

    • 什么是“GetGlobalService”?我在 VS2010,也许是 2012 年的特定项目?
    • GetGlobalService 是 Microsoft.VisualStudio.Shell.Package 上的一个方法,我的扩展是它的子类。
    【解决方案3】:

    对于未来的读者,请查看这篇文章。

    http://blogs.msdn.com/b/alexpetr/archive/2012/08/14/visual-studio-2012-and-buildevents-in-addins.aspx

    和/或

    http://support.microsoft.com/kb/555102/en-us

    基本上,可能存在错误。 解决方法是在 Connect 上设置“.BuildEvents”的成员变量。

    例子:

    private _BuildEvents _buildEvents;
    
    public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
                  {
                    _buildEvents = _applicationObject.Events.BuildEvents;
                  }
    

    然后将事件处理程序连接到

    this._buildEvents
    

    而不是

    _applicationObject.Events.BuildEvents
    

    其中 _applicationObject = (EnvDTE.DTE)应用程序;

    至少值得一试,恕我直言。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多