2010-05-10 3 views
10

Sto scrivendo un componente aggiuntivo VS e ho bisogno di eseguire un determinato metodo dopo una build di successo. Ho provato a usare dte.Events.BuildEvents.OnBuildDone ma quell'evento si verifica anche se la compilazione falliva.Come ricevere una notifica al termine di una build completata?

Esiste una proprietà o qualche altro evento che dovrei usare?

risposta

13

L'evento OnBuildDone non può dirti cosa è successo. Alcuni progetti nella soluzione potrebbero essere stati creati correttamente, altri no. Avrai invece bisogno di OnBuildProjConfigDone. Incendi per ogni progetto, l'argomento Successo ti dice se ha funzionato.

+0

Nel mio caso OnBuildDone non ha mai funzionato, ma OnBuildProjConfigDone ha funzionato bene –

+0

@DinisCruz A volte OnBuildDone non si attiva se non si mantiene il riferimento a dte.Events.BuildEvents – Artiom

+1

Esiste un esempio di codice completo su come eseguire questa operazione qui: https://github.com/edsykes/VisualStudioBuildEvents –

6

In genere, è necessario gestire più progetti in corso di creazione. Potrebbe essere una soluzione da costruire o la costruzione di un progetto che dipende da un altro progetto.

Così, per capire quando una creazione che è terminata, è necessario utilizzare una combinazione dei due eventi di generazione:

OnBuildProjConfigDone e OnBuildDone.

Avrai anche bisogno di una variabile membro per tenere traccia dello stato generale della costruzione.

Il tuo gestore OnBuildProjConfigDone verrà chiamato per ogni progetto che viene generato e viene passato un bool per dirti se la creazione del progetto ha avuto successo. Assegna questo risultato alla tua variabile membro per tenere traccia dello stato generale.

Infine, il gestore OnBuildDone verrà chiamato. Qui puoi vedere la tua variabile membro per vedere se qualche build del progetto è fallita.

Ecco un esempio di codice da un'estensione che ho scritto per VS2012. L'estensione fornisce un comando "custom build" che crea il progetto attivo e avvia il debugger se la compilazione ha avuto successo.

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); 
} 
+0

Che cos'è il "GetGlobalService"? Sono su VS2010, forse un articolo specifico del 2012? – granadaCoder

+0

GetGlobalService è un metodo su Microsoft.VisualStudio.Shell.Package, che la mia estensione sottoclasse. – ryanman

2

Per i futuri lettori, dai un'occhiata a questo articolo.

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

e/o

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

In sostanza, ci potrebbe essere un bug. La soluzione consiste nell'impostare una variabile membro di ".BuildEvents" su Connect.

Esempio:

private _BuildEvents _buildEvents; 

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

Poi cablare i gestori di eventi per

this._buildEvents 

e non

_applicationObject.Events.BuildEvents 

dove _applicationObject = (EnvDTE.DTE) applicazione;

Vale la pena provare almeno, IMHO.

+0

Spara. Ora che ho scritto quanto sopra, ho trovato un'ottima risposta SOF. http://stackoverflow.com/questions/14165885/add-in-events-are-never-executed – granadaCoder