Descripción del archivo de proyecto

por Jason Lee

Microsoft Build Engine archivos de proyecto (MSBuild) se encuentran en el centro del proceso de compilación e implementación. Este tema comienza con una introducción conceptual de MSBuild y el archivo de proyecto. Describe los componentes clave que encontrará al trabajar con archivos de proyecto y funciona a través de un ejemplo de cómo puede usar archivos de proyecto para implementar aplicaciones reales.

Temas que se abordarán:

  • Cómo MSBuild usa archivos de proyecto de MSBuild para compilar proyectos.
  • Cómo se integra MSBuild con tecnologías de implementación, como internet Information Services (IIS) Web Deployment Tool (Web Deploy).
  • Cómo comprender los componentes clave de un archivo de proyecto.
  • Cómo puede usar archivos de proyecto para compilar e implementar aplicaciones complejas.

MSBuild y el archivo de proyecto

Al crear y compilar soluciones en Visual Studio, Visual Studio usa MSBuild para compilar cada proyecto de la solución. Cada proyecto de Visual Studio incluye un archivo de proyecto de MSBuild, con una extensión de archivo que refleja el tipo de proyecto( por ejemplo, un proyecto de C# (.csproj), un proyecto de Visual Basic.NET (.vbproj) o un proyecto de base de datos (.dbproj). Para compilar un proyecto, MSBuild debe procesar el archivo de proyecto asociado al proyecto. El archivo del proyecto es un documento XML que contiene toda la información e instrucciones que MSBuild necesita para compilar el proyecto, como el contenido que se va a incluir, los requisitos de la plataforma, la información de control de versiones, la configuración del servidor web o del servidor de base de datos, y las tareas que se deben realizar.

Los archivos de proyecto de MSBuild se basan en el esquema XML de MSBuild y, como resultado, el proceso de compilación es totalmente abierto y transparente. Además, no es necesario instalar Visual Studio para usar el motor de MSBuild: el archivo ejecutable de MSBuild.exe forma parte de .NET Framework y puede ejecutarlo desde un símbolo del sistema. Como desarrollador, puede crear sus propios archivos de proyecto de MSBuild, mediante el esquema XML de MSBuild, para imponer un control sofisticado y específico sobre cómo se compilan e implementan los proyectos. Estos archivos de proyecto personalizados funcionan exactamente de la misma manera que los archivos de proyecto que Visual Studio genera automáticamente.

Nota

También puede usar archivos de proyecto de MSBuild con el servicio Team Build en Team Foundation Server (TFS). Por ejemplo, puede usar archivos de proyecto en escenarios de integración continua (CI) para automatizar la implementación en un entorno de prueba cuando se activa código nuevo. Para obtener más información, consulte Configuración de Team Foundation Server para la implementación web automatizada.

Convenciones de nomenclatura de archivos de proyecto

Al crear sus propios archivos de proyecto, puede usar cualquier extensión de archivo que desee. Sin embargo, para que las soluciones sean más fáciles de entender, debe usar estas convenciones comunes:

  • Use la extensión .proj al crear un archivo de proyecto que compile proyectos.
  • Use la extensión .targets al crear un archivo de proyecto reutilizable para importar en otros archivos de proyecto. Los archivos con una extensión .targets normalmente no compilan nada por sí mismos, simplemente contienen instrucciones que se pueden importar en los archivos .proj.

Integración con tecnologías de implementación

Si ha trabajado con proyectos de aplicaciones web en Visual Studio 2010, como ASP.NET aplicaciones web y ASP.NET aplicaciones web MVC, sabrá que estos proyectos incluyen compatibilidad integrada para empaquetar e implementar la aplicación web en un entorno de destino. Las páginas Propiedades de estos proyectos incluyen pestañas Package/Publish Web y Package/Publish SQL que puede usar para configurar cómo se empaquetan e implementan los componentes de la aplicación. Esto muestra la pestaña Web Package/Publish:

La pestaña Paquete/Publicar web

La tecnología subyacente detrás de estas funcionalidades se conoce como canalización de publicación web (WPP). WpP básicamente reúne MSBuild e Web Deploy para proporcionar un proceso completo de compilación, paquete e implementación para las aplicaciones web.

La buena noticia es que puede aprovechar los puntos de integración que proporciona WPP al crear archivos de proyecto personalizados para proyectos web. Puede incluir instrucciones de implementación en el archivo del proyecto, lo que le permite compilar los proyectos, crear paquetes de implementación web e instalar estos paquetes en servidores remotos a través de un único archivo de proyecto y una sola llamada a MSBuild. También puede llamar a cualquier otro ejecutable como parte del proceso de compilación. Por ejemplo, puede ejecutar la herramienta de línea de comandos VSDBCMD.exe para implementar una base de datos desde un archivo de esquema. A lo largo de este tema, verá cómo puede aprovechar estas funcionalidades para cumplir los requisitos de los escenarios de implementación empresarial.

Nota

Para obtener más información sobre cómo funciona el proceso de implementación de aplicaciones web, consulte ASP.NET Información general sobre la implementación del proyecto de aplicación web.

Anatomía de un archivo de proyecto

Antes de examinar el proceso de compilación con más detalle, merece la pena familiarizarse con la estructura básica de un archivo de proyecto de MSBuild. En esta sección se proporciona información general sobre los elementos más comunes que encontrará al revisar, editar o crear un archivo de proyecto. En concreto, aprenderá lo siguiente:

  • Cómo usar propiedades para administrar variables para el proceso de compilación.
  • Cómo usar elementos para identificar las entradas para el proceso de compilación, como los archivos de código.
  • Cómo usar destinos y tareas para proporcionar instrucciones de ejecución a MSBuild mediante propiedades y elementos definidos en otro lugar del archivo de proyecto.

Esto muestra la relación entre los elementos clave de un archivo de proyecto de MSBuild:

Relación entre los elementos clave de un archivo de proyecto de MSBuild.

Elemento Project

El elemento Project es el elemento raíz de cada archivo de proyecto. Además de identificar el esquema XML para el archivo de proyecto, el elemento Project puede incluir atributos para especificar los puntos de entrada para el proceso de compilación. Por ejemplo, en la solución de ejemplo Contact Manager, el archivo Publish.proj especifica que la compilación debe empezar llamando al destino denominado FullPublish.

<Project ToolsVersion="4.0" DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
</Project>

Propiedades y condiciones

Normalmente, un archivo de proyecto debe proporcionar muchos fragmentos de información diferentes para compilar e implementar correctamente los proyectos. Estos fragmentos de información podrían incluir nombres de servidor, cadenas de conexión, credenciales, configuraciones de compilación, rutas de acceso de archivo de origen y de destino, y cualquier otra información que quiera incluir para admitir la personalización. En un archivo de proyecto, las propiedades deben definirse dentro de un elemento PropertyGroup . Las propiedades de MSBuild constan de pares clave-valor. Dentro del elemento PropertyGroup , el nombre del elemento define la clave de propiedad y el contenido del elemento define el valor de propiedad. Por ejemplo, podría definir propiedades denominadas ServerName y ConnectionString para almacenar un nombre de servidor estático y cadena de conexión.

<PropertyGroup>    
   <ServerName>FABRIKAM\TEST1</ServerName>
   <ConnectionString>
     Data Source=FABRIKAM\TESTDB;InitialCatalog=ContactManager,...
   </ConnectionString>
</PropertyGroup>

Para recuperar un valor de propiedad, use el formato $(PropertyName). Por ejemplo, para recuperar el valor de la propiedad ServerName , escribiría:

$(ServerName)

Nota

Verá ejemplos de cómo y cuándo usar valores de propiedad más adelante en este tema.

La inserción de información como propiedades estáticas en un archivo de proyecto no siempre es el enfoque ideal para administrar el proceso de compilación. En muchos escenarios, querrá obtener la información de otros orígenes o permitir al usuario proporcionar la información desde el símbolo del sistema. MSBuild permite especificar cualquier valor de propiedad como parámetro de línea de comandos. Por ejemplo, el usuario podría proporcionar un valor para ServerName cuando ejecuta MSBuild.exe desde la línea de comandos.

msbuild.exe Publish.proj /p:ServerName=FABRIKAM\TESTWEB1

Nota

Para obtener más información sobre los argumentos y modificadores que puede usar con MSBuild.exe, vea Referencia de línea de comandos de MSBuild.

Puede usar la misma sintaxis de propiedad para obtener los valores de las variables de entorno y las propiedades del proyecto integradas. Se definen muchas propiedades usadas habitualmente y puede usarlas en los archivos del proyecto incluyendo el nombre de parámetro correspondiente. Por ejemplo, para recuperar la plataforma de proyecto actual (por ejemplo, x86 o AnyCpu), puede incluir la referencia de propiedad $(Platform) en el archivo del proyecto. Para obtener más información, vea Macros para comandos y propiedades de compilación, Propiedades comunes del proyecto de MSBuild y Propiedades reservadas.

Las propiedades se suelen usar junto con condiciones. La mayoría de los elementos de MSBuild admiten el atributo Condition , que permite especificar los criterios en los que MSBuild debe evaluar el elemento. Por ejemplo, considere esta definición de propiedad:

<PropertyGroup>
   <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
   ...
</PropertyGroup>

Cuando MSBuild procesa esta definición de propiedad, primero comprueba si hay disponible un valor de propiedad $(OutputRoot). Si el valor de la propiedad está en blanco (es decir, el usuario no ha proporcionado un valor para esta propiedad), la condición se evalúa como true y el valor de propiedad se establece en .. \Publish\Out. Si el usuario ha proporcionado un valor para esta propiedad, la condición se evalúa como false y el valor de la propiedad estática no se usa.

Para obtener más información sobre las distintas formas en las que puede especificar condiciones, consulte Condiciones de MSBuild.

Elementos y grupos de elementos

Uno de los roles importantes del archivo de proyecto es definir las entradas para el proceso de compilación. Normalmente, estas entradas son archivos: archivos de código, archivos de configuración, archivos de comandos y cualquier otro archivo que necesite procesar o copiar como parte del proceso de compilación. En el esquema del proyecto de MSBuild, estas entradas se representan mediante elementos Item . En un archivo de proyecto, los elementos deben definirse dentro de un elemento ItemGroup . Al igual que los elementos Property , puede asignar un nombre a un elemento Item como quiera. Sin embargo, debe especificar un atributo Include para identificar el archivo o comodín que representa el elemento.

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

Al especificar varios elementos Item con el mismo nombre, se crea eficazmente una lista con nombre de recursos. Una buena manera de ver esto en acción es echar un vistazo dentro de uno de los archivos de proyecto que crea Visual Studio. Por ejemplo, el archivo ContactManager.Mvc.csproj de la solución de ejemplo incluye una gran cantidad de grupos de elementos, cada uno con varios elementos con un nombre idéntico.

<ItemGroup>
   <Reference Include="Microsoft.CSharp" />
   <Reference Include="System.Runtime.Serialization" />
   <Reference Include="System.ServiceModel" />
   ...
</ItemGroup>
<ItemGroup>
   <Compile Include="Controllers\AccountController.cs" />
   <Compile Include="Controllers\ContactsController.cs" />
   <Compile Include="Controllers\HomeController.cs" />
   ...
</ItemGroup>
<ItemGroup>
   <Content Include="Content\Custom.css" />
   <Content Include="CreateDatabase.sql" />
   <Content Include="DropDatabase.sql" />
   ...
</ItemGroup>

De este modo, el archivo de proyecto indica a MSBuild que construya listas de archivos que deben procesarse de la misma manera: la lista de referencias incluye ensamblados que deben estar en vigor para una compilación correcta, la lista Compilar incluye archivos de código que se deben compilar y la lista contenido incluye recursos que se deben copiar sin modificar. Veremos cómo hace referencia el proceso de compilación y usa estos elementos más adelante en este tema.

Los elementos Item también pueden incluir elementos secundarios ItemMetadata . Se trata de pares clave-valor definidos por el usuario y, básicamente, representan propiedades específicas de ese elemento. Por ejemplo, muchos de los elementos Compile item del archivo de proyecto incluyen elementos secundarios DependentUpon .

<Compile Include="Global.asax.cs">
   <DependentUpon>Global.asax</DependentUpon>
</Compile>

Nota

Además de los metadatos de elementos creados por el usuario, a todos los elementos se les asignan varios metadatos comunes sobre la creación. Para obtener más información, vea Metadatos de elementos conocidos.

Puede crear elementos ItemGroup dentro del elemento Project de nivel raíz o dentro de elementos Target específicos. Los elementos ItemGroup también admiten atributos Condition , lo que permite adaptar las entradas al proceso de compilación según condiciones como la configuración del proyecto o la plataforma.

Destinos y tareas

En el esquema de MSBuild, un elemento Task representa una instrucción de compilación individual (o tarea). MSBuild incluye una gran cantidad de tareas predefinidas. Por ejemplo:

  • La tarea Copiar copia archivos en una nueva ubicación.
  • La tarea Csc invoca al compilador de Visual C#.
  • La tarea Vbc invoca al compilador de Visual Basic.
  • La tarea Exec ejecuta un programa especificado.
  • La tarea Mensaje escribe un mensaje en un registrador.

Nota

Para obtener detalles completos de las tareas que están disponibles de forma predeterminada, consulte Referencia de tareas de MSBuild. Para obtener más información sobre las tareas, incluido cómo crear sus propias tareas personalizadas, consulte Tareas de MSBuild.

Las tareas siempre deben estar contenidas en los elementos Target . Un elemento Target es un conjunto de una o varias tareas que se ejecutan secuencialmente y un archivo de proyecto puede contener varios destinos. Cuando quiera ejecutar una tarea o un conjunto de tareas, invoque el destino que los contiene. Por ejemplo, supongamos que tiene un archivo de proyecto simple que registra un mensaje.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

Puede invocar el destino desde la línea de comandos mediante el modificador /t para especificar el destino.

msbuild.exe Publish.proj /t:LogMessage

Como alternativa, puede agregar un atributo DefaultTargets al elemento Project para especificar los destinos que desea invocar.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
         DefaultTargets="FullPublish">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

En este caso, no es necesario especificar el destino desde la línea de comandos. Simplemente puede especificar el archivo de proyecto y MSBuild invocará el destino FullPublish automáticamente.

msbuild.exe Publish.proj

Tanto los destinos como las tareas pueden incluir atributos Condition . Por lo tanto, puede optar por omitir destinos completos o tareas individuales si se cumplen determinadas condiciones.

Por lo general, al crear tareas y destinos útiles, deberá hacer referencia a las propiedades y los elementos que ha definido en otro lugar del archivo de proyecto:

  • Para usar un valor de propiedad, escriba $(PropertyName), donde PropertyName es el nombre del elemento Property o el nombre del parámetro.
  • Para usar un elemento, escriba @(ItemName), donde ItemName es el nombre del elemento Item .

Nota

Recuerde que si crea varios elementos con el mismo nombre, va a crear una lista. Por el contrario, si crea varias propiedades con el mismo nombre, el último valor de propiedad que proporcione sobrescribirá las propiedades anteriores con el mismo nombre, una propiedad solo puede contener un único valor.

Por ejemplo, en el archivo Publish.proj de la solución de ejemplo, eche un vistazo al destino BuildProjects .

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"           
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
</Target>

En este ejemplo, puede observar estos puntos clave:

  • Si se especifica el parámetro BuildingInTeamBuild y tiene un valor true, no se ejecutará ninguna de las tareas de este destino.

  • El destino contiene una única instancia de la tarea de MSBuild . Esta tarea le permite compilar otros proyectos de MSBuild.

  • El elemento ProjectsToBuild se pasa a la tarea. Este elemento podría representar una lista de archivos de proyecto o solución, todos definidos por los elementos de elemento ProjectsToBuild dentro de un grupo de elementos. En este caso, el elemento ProjectsToBuild hace referencia a un único archivo de solución.

    <ItemGroup>
       <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
    </ItemGroup>
    
  • Los valores de propiedad pasados a la tarea de MSBuild incluyen parámetros denominados OutputRoot y Configuration. Se establecen en valores de parámetro si se proporcionan, o valores de propiedad estáticos si no lo son.

    <PropertyGroup>
       ... 
       <Configuration Condition=" '$(Configuration)'=='' ">Release
       </Configuration>
       <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\
       </OutputRoot>
       ...
    </PropertyGroup>
    

También puede ver que la tarea de MSBuild invoca un destino denominado Build. Se trata de uno de los varios destinos integrados que se usan ampliamente en los archivos de proyecto de Visual Studio y que están disponibles para usted en los archivos de proyecto personalizados, como Build, Clean, Rebuild y Publish. Obtendrá más información sobre el uso de destinos y tareas para controlar el proceso de compilación y sobre la tarea de MSBuild en particular, más adelante en este tema.

Nota

Para más información sobre los destinos, consulte Destinos de MSBuild.

Dividir archivos de proyecto para admitir varios entornos

Supongamos que desea poder implementar una solución en varios entornos, como servidores de prueba, plataformas de ensayo y entornos de producción. La configuración puede variar considerablemente entre estos entornos, no solo en términos de nombres de servidor, cadenas de conexión, etc., sino también en términos de credenciales, configuración de seguridad y muchos otros factores. Si necesita hacerlo con regularidad, no es conveniente editar varias propiedades en el archivo del proyecto cada vez que cambie el entorno de destino. Tampoco es una solución ideal para requerir que se proporcione una lista infinita de valores de propiedad al proceso de compilación.

Afortunadamente hay una alternativa. MSBuild le permite dividir la configuración de compilación en varios archivos de proyecto. Para ver cómo funciona, en la solución de ejemplo, observe que hay dos archivos de proyecto personalizados:

  • Publish.proj, que contiene propiedades, elementos y destinos comunes a todos los entornos.
  • Env-Dev.proj, que contiene propiedades específicas de un entorno de desarrollador.

Ahora observe que el archivo Publish.proj incluye un elemento Import , inmediatamente debajo de la etiqueta Project de apertura.

<Import Project="$(TargetEnvPropsFile)"/>

El elemento Import se usa para importar el contenido de otro archivo de proyecto de MSBuild en el archivo de proyecto de MSBuild actual. En este caso, el parámetro TargetEnvPropsFile proporciona el nombre de archivo del archivo de proyecto que desea importar. Puede proporcionar un valor para este parámetro al ejecutar MSBuild.

msbuild.exe Publish.proj /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

Esto combina eficazmente el contenido de los dos archivos en un único archivo de proyecto. Con este enfoque, puede crear un archivo de proyecto que contenga la configuración de compilación universal y varios archivos de proyecto complementarios que contengan propiedades específicas del entorno. Como resultado, simplemente ejecutar un comando con un valor de parámetro diferente le permite implementar la solución en un entorno diferente.

La ejecución de un comando con un valor de parámetro diferente le permite implementar la solución en un entorno diferente.

Dividir los archivos del proyecto de esta manera es una buena práctica para seguir. Permite a los desarrolladores implementar en varios entornos mediante la ejecución de un único comando, a la vez que evitan la duplicación de propiedades de compilación universal en varios archivos de proyecto.

Nota

Para obtener instrucciones sobre cómo personalizar los archivos de proyecto específicos del entorno para sus propios entornos de servidor, consulte Configuración de propiedades de implementación para un entorno de destino.

Conclusión

En este tema se proporciona una introducción general a los archivos de proyecto de MSBuild y se explica cómo crear sus propios archivos de proyecto personalizados para controlar el proceso de compilación. También introdujo el concepto de dividir archivos de proyecto en instrucciones de compilación universales y propiedades de compilación específicas del entorno, para facilitar la compilación e implementación de proyectos en varios destinos.

En el tema siguiente, Descripción del proceso de compilación, se proporciona más información sobre cómo puede usar archivos de proyecto para controlar la compilación e implementación, para lo que le guiará a través de la implementación de una solución con un nivel realista de complejidad.

Lecturas adicionales

Para obtener una introducción más detallada a los archivos de proyecto y el WPP, consulte Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build by Sayed Ibrahim Hashimi and William Bartholomew, ISBN: 978-0-7356-4524-0.