tutorial navisworks español visual-studio projects-and-solutions pre-build-event

visual-studio - tutorial - manual de navisworks 2018 en español pdf



¿Evento previo a la construcción en toda la solución? (6)

Tengo una solución en Visual Studio que contiene varios proyectos. Me gustaría ejecutar un comando al comienzo de cada compilación, sin importar qué proyectos estén involucrados y si están actualizados o no.

Básicamente, necesito algo similar a un evento previo a la construcción en toda la solución, pero desafortunadamente VS no parece ser compatible. ¿Alguien sabe una forma alternativa de lograr lo que necesito?


Ha pasado un tiempo, y algunas cosas en la infraestructura de .Net han cambiado desde entonces, dando nuevas opciones. Ahora mi elección para resolver este rey del problema son los paquetes nuget. Puse mis pasos de compilación en un paquete que luego se incluyó en cada proyecto. De manera amigable, el administrador de paquetes de Visual Studio ofrece una descripción general de los paquetes en el nivel de solución, por lo que es muy fácil verificar esta regla.


Hacemos esto agregando un proyecto vacío y estableciendo eventos de compilación para este proyecto. Luego, debe asignar cada dependencia de proyecto a este proyecto vacío para asegurarse de que se genera cada vez.


Otra publicación anterior pero inspirada en la solución @reg. Quería ejecutar un temporizador de compilación simple que registraría el tiempo transcurrido para la creación de una solución. Obtuve los eventos de compilación trabajando usando un módulo de PowerShell que cargué a través de la consola del gestor de paquetes cuando se inicia el IDE de Visual Studio.

Así que crea un módulo de powershell como BuildEvents.psm1 :

<# .SYNOPSIS Register solution build events .DESCRIPTION Registers the OnBuildBegin and OnBuildDone events for the entire solution De-registers the events if called multiple times. .EXAMPLE RegisterBuildEvents #> function RegisterBuildEvents{ try { Unregister-Event -SourceIdentifier "OnBuildBegin" -Force } catch { #we don''t care if this doesn''t work } try { Unregister-Event -SourceIdentifier "OnBuildDone" -Force } catch { #we don''t care if this doesn''t work } $obj = [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($dte.Application.Events.BuildEvents, [EnvDTE.BuildEventsClass]) Register-ObjectEvent -InputObject $obj -EventName OnBuildBegin -Action { # do stuff here on build begin Write-Host "Solution build started!" } -SourceIdentifier "OnBuildBegin" Register-ObjectEvent -InputObject $obj -EventName OnBuildDone -Action { # do stuff here on build done Write-Host "Solution build done!" } -SourceIdentifier "OnBuildDone" } # export the functions from the module export-modulemember -function RegisterBuildEvents

Importe el módulo cuando el host del Administrador de paquetes inicie:

  1. En la consola del gestor de paquetes, escriba $ profile para obtener la ubicación de su perfil de powershell
  2. Navegue a ese directorio en el disco, si no hay ningún archivo, cree uno con el nombre devuelto por el comando anterior (por ejemplo, NuGet_profile.ps1 )
  3. Abra el archivo en el bloc de notas y agregue las siguientes líneas

    Import-Module -Name <Path to your ps module>/BuildEvents -Force RegisterBuildEvents



Requisito inusual. Pero puede hacerse. Agregue un nuevo proyecto a su solución, use la plantilla Visual C ++> General> Makefile Project. Establezca su configuración NMake> Build Command Line en los comandos que desea ejecutar. Use Proyecto> Dependencias del proyecto para que todos los demás proyectos dependan de él.


Breve resumen de mis variantes a continuación

solo una nota: es una lista incompleta de todas las existentes (ver también otras respuestas, etc.), solo apoyo mis trucos originales en el estado actual ...

Notas:

  • 1 - No requiere extensiones adicionales. Pero puede funcionar únicamente a través de proyectos, por lo que lo usamos para emular el nivel de nuestra solución ... Es difícil e inconveniente para una solución común, pero es una variante. Vea abajo.
  • 2 - El motor original de vsSolutionBuildEvent proporciona algunas formas de soporte unificado de VS y msbuild.exe. Una forma simple el targets mode para llamar al after.<name>.sln.targets que está disponible solo para msbuild.exe (esto no requiere pasos adicionales, simplemente acción). Pero solo el motor original (inc. VsCommandEvent) puede permitir secuencias de comandos adicionales, que admiten, por ejemplo, (archivador 7zip, empaquetado del paquete nuget sin nuget.exe, servidores remotos, etc.). Sin embargo, no es importante para nuestra pregunta / problema y puede usar cualquier opción disponible para respaldar el nivel de la solución si ve + arriba.

Variante 1: Microsoft.VisualStudio.Shell.Interop

Esta variante no es para usuarios simples de VS. Sin embargo, puede ser útil para su solución completa, etc.

Debe implementar, por ejemplo:

p.ej:

public sealed class YourPackage: Package, IVsSolutionEvents, IVsUpdateSolutionEvents2 { ... public int UpdateSolution_Begin(ref int pfCancelUpdate) { //TODO: } }

A continuación, registre el controlador con los métodos ''Advise'' como detector de prioridad, es decir, para IVsUpdateSolutionEvents2 debe usar AdviseUpdateSolutionEvents

Es importante , porque BuildEvents (ver EnvDTE ) - probablemente no ayude y puede que funcione demasiado tarde - Example

Muestra con AdviseUpdateSolutionEvents:

// http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.ivssolutionbuildmanager2.aspx private IVsSolutionBuildManager2 sbm; // http://msdn.microsoft.com/en-us/library/bb141335.aspx private uint _sbmCookie; ... sbm = (IVsSolutionBuildManager2)ServiceProvider.GlobalProvider.GetService(typeof(SVsSolutionBuildManager)); sbm.AdviseUpdateSolutionEvents(this, out _sbmCookie);

Dónde:

  • el campo sbm debe ser parte de la clase para protección contra GC.
  • para obtener el servicio SVsSolutionBuildManager se utiliza ServiceProvider pero puede ser lo que necesite. Ver msdn

Ahora podemos trabajar con todos los proyectos a la vez: a nivel de solución.

Variante 2: Objetivos y mapa de proyectos.

vale, adoras algo como esto - after.<name>.sln.targets , pero esta variante puede funcionar con los procesos de compilación desde msbuild.exe y no desde VS IDE ...

Pero el VS también usa objetivos (Build, Rebuild, Clean, ..) en los archivos del proyecto (* .csproj, * .vcxproj, ..) cuando se inician las operaciones de compilación. Entonces también podemos intentar esto, pero recuerde:

  • El VS también ignora el asombroso archivo .sln. Forma todos los objetivos finales del entorno cargado con EnvDTE, etc.
  • El archivo .sln debe ser procesado por msbuild.exe solo de la siguiente manera: generar automáticamente el archivo .metaproj (en la memoria por defecto), que contiene ''qué y cuándo'' se generará. Incluyendo un objetivo común para todos los proyectos si existe, por ejemplo:

... <Import Project="$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/SolutionFile/ImportAfter/*" Condition="''$(ImportByWildcardBeforeSolution)'' != ''false'' and exists(''$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/SolutionFile/ImportAfter'')" /> <Import Project="D:/tmp/p/after.name.sln.targets" Condition="exists(''D:/tmp/p/after.name.sln.targets'')" /> <Target Name="Build" /> <Target Name="Rebuild" /> <Target Name="Clean" /> <Target Name="Publish" />

  • Y sí, el .metaproj tampoco puede ser visto por VS IDE.

Por lo tanto, para trabajar con objetivos comunes de VS IDE, puede usar solo archivos de proyecto con alguna limitación (sin modificación / extensión de VS, es decir).

Y así, si necesita la solución común (es decir, puede que no sepa sobre proyectos, etc.), puede ser, por ejemplo, para algunas soluciones de caja y similares :

  • Agregue su archivo .targets común en todos sus proyectos (puede ser automáticamente con cualquier herramienta, inc. Los eventos NuGet, etc.), por ejemplo: <Import Project="../<SolutionFile>.targets" />
  • Entonces, debes usar alguna limitación para:
    • "solo - antes de todos los proyectos"
    • "solo - después de todos los proyectos"

Y por ejemplo, sí, puede ser el ''Mapa de proyectos'':

  • El ''Mapa de proyectos'' ilustra los ''eventos'' PRE / POST en toda la solución para las operaciones de compilación desde Visual Studio IDE (es decir, primario desde VS IDE)

... <Target Name="_Build" BeforeTargets="Build" DependsOnTargets="ProjectsMap"> <CallTarget Targets="_BuildPRE" Condition="$(ScopeDetectFirst)" /> <CallTarget Targets="_BuildPOST" Condition="$(ScopeDetectLast)" /> </Target> <Target Name="_BuildPRE"> <!-- ... --> </Target> <Target Name="_BuildPOST"> <!-- ... --> </Target> ...

En general, usaremos el mapa de proyectos y ahora sabemos ''qué y cuándo'' debería suceder. Es seguro para todos o la mayoría de los casos (cambios en el orden de compilación o eliminación de cualquier proyecto de la solución). ¡Sin embargo! debe administrar la sección <Import> para nuevos proyectos en el primer inicio. Esto es realmente inconveniente, pero también es una variante ...

Variante 3: Complemento vsSolutionBuildEvent

Hoy es la solución más completa para trabajar con muchos eventos como Events-Catcher con una variedad de acciones avanzadas para el mantenimiento de sus proyectos y bibliotecas, creando procesos y procesos en tiempo de ejecución desde su Visual Studio y MSBuild Tool.

Diferentes tipos de acciones para todos los subproyectos a la vez en solución como Solution-Events o individualmente para cada uno.

https://visualstudiogallery.msdn.microsoft.com/0d1dbfd7-ed8a-40af-ae39-281bfeca2334/

Cómo funciona adentro

Si desea utilizar la Variante 1 anterior o necesita ver cómo trabajar con Shell.Interop, EnvDTE, IVsUpdateSolutionEvents2, MSBuild Engine, etc., consulte here :

here

Variante 4. EnvDTE.CommandEvents

Esta variante tampoco es para usuarios simples de VS. Sin embargo, en cuanto a la Variante 1 , puede ser útil para su solución de caja, etc.

No es lo mismo, pero sí, también es posible con EnvDTE.CommandEvents como en la variante 1 anterior.

Ya debe saber (ver más arriba) acerca de esta solución para el trabajo prioritario con el tipo actual de la acción de compilación ... Entonces, ¿por qué no utilizar esto como solución principal para el problema actual?

_cmdEvents.BeforeExecute += (string guid, int id, object customIn, object customOut, ref bool cancelDefault) => { if(UnifiedTypes.Build.VSCommand.existsById(id)) { // ... your action } };

Dónde: Description | guid | id |In |Out| --------------------------|---------------------------------------|-----|---|---| Started: Build Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 882 | | | Started: Rebuild Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 883 | | | Started: Clean Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 885 | | | Description | guid | id |In |Out| --------------------------|---------------------------------------|-----|---|---| Started: Build Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 882 | | | Started: Rebuild Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 883 | | | Started: Clean Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 885 | | |

http://vsce.r-eg.net/doc/Features/Solution-wide/

Además, opcional, puede suprimir estos comandos si lo necesita. En la variante a continuación, verá la solución completa de esta manera.

Variante 5. Complemento vsCommandEvent

https://visualstudiogallery.msdn.microsoft.com/ad9f19b2-04c0-46fe-9637-9a52ce4ca661/

También presenta un controlador avanzado de la mayoría de los eventos, pero a diferencia del primero, se especializó en MS Visual Studio para un trabajo avanzado con todos los comandos y datos de salida como administrador de este. No solo para proyectos y soluciones, sino también para todo el Visual Studio IDE.

En general, es la solución común de la Variante 4 y puede simplemente anular todos los comandos anteriores para resolver este problema.

Y para el mismo modelo de Event-Actions como en vsSolutionBuildEvent, puede ser útil para la mayoría de los casos.

"Ayudame con variantes"

Hay una implementación abierta para todas estas variantes. Mira aquí y sonríe :