propiedades de MSBuild

Las propiedades son pares nombre-valor que se pueden utilizar para configurar compilaciones. Las propiedades son útiles para pasar valores a tareas, evaluar condiciones y almacenar valores a los que se hará referencia en el archivo del proyecto.

Definir y hacer referencia a propiedades en un archivo de proyecto

Las propiedades se declaran mediante la creación de un elemento que tenga el nombre de la propiedad como elemento secundario de un elemento PropertyGroup. Por ejemplo, el código XML siguiente crea una propiedad denominada BuildDir cuyo valor es Build.

<PropertyGroup>
    <BuildDir>Build</BuildDir>
</PropertyGroup>

Los nombres de propiedades válidos comienzan con una letra mayúscula o minúscula o un carácter de subrayado (_); los caracteres posteriores válidos incluyen caracteres alfanuméricos (letras o dígitos), caracteres de subrayado y guión (-).

En el archivo del proyecto, se hace referencia a las propiedades mediante la sintaxis $(<PropertyName>). En el ejemplo anterior, se usa $(BuildDir) para hacer referencia a la propiedad.

Los valores de propiedad se pueden cambiar si se vuelve a definir la propiedad. Se puede asignar un nuevo valor a la propiedad BuildDir mediante este código XML:

<PropertyGroup>
    <BuildDir>Alternate</BuildDir>
</PropertyGroup>

Las propiedades se evalúan en el orden en que aparecen en el archivo del proyecto. El nuevo valor de BuildDir debe declararse después de que se haya asignado el valor anterior.

Propiedades reservadas

MSBuild reserva algunos nombres de propiedades para almacenar información sobre el archivo del proyecto y los archivos binarios de MSBuild. Como a cualquier otra propiedad, a estas propiedades se hace referencia mediante la notación $. Por ejemplo, $(MSBuildProjectFile) devuelve el nombre de archivo completo del proyecto, incluida la extensión.

Para obtener más información, vea Cómo: Hacer referencia al nombre o la ubicación del archivo del proyecto y Propiedades reservadas y conocidas de MSBuild.

Propiedades internas de MSBuild

Las propiedades definidas en los archivos de importación estándar que comienzan por un carácter de subrayado (_) son privadas de MSBuild y no deben leerse, restablecerse ni invalidarse en el código de usuario.

Propiedades de entorno

En los archivos de proyecto, se puede hacer referencia a las variables de entorno de la misma manera que en el caso de las propiedades reservadas. Por ejemplo, para utilizar la variable de entorno PATH en el archivo de proyecto, utilice $(Path). Si el proyecto incluye la definición de una propiedad que tiene el mismo nombre que una propiedad de entorno, la propiedad del proyecto reemplaza el valor de la propiedad de entorno.

Cada proyecto de MSBuild tiene un bloque de entorno aislado: solo ve las lecturas y escrituras de su propio bloque. MSBuild solo lee las variables de entorno cuando inicializa la colección de propiedades, antes de que se evalúe o compile el archivo de proyecto. Después, las propiedades del entorno son estáticas, es decir, cada herramienta generada se inicia con los mismos nombres y valores.

Para obtener el valor actual de las variables de entorno desde una herramienta generada, use las Funciones de propiedad System.Environment.GetEnvironmentVariable. Sin embargo, el método preferido es usar el parámetro de tarea EnvironmentVariables. Las propiedades de entorno establecidas en esta matriz de cadenas se pueden pasar a la herramienta generada sin afectar a las variables de entorno del sistema.

Sugerencia

No todas las variables de entorno se leen para convertirse en propiedades iniciales. Las variables de entorno cuyo nombre no sea un nombre de propiedad de MSBuild válido, como "386", se omiten.

Para obtener más información, vea Cómo: Usar variables de entorno al compilar.

Propiedades del Registro

Para leer los valores del Registro del sistema, use la sintaxis siguiente, donde Hive es el subárbol del Registro (por ejemplo, HKEY_LOCAL_MACHINE), MyKey es el nombre de clave, MySubKey es el nombre de subclave y Value es el valor de la subclave.

$(registry:Hive\MyKey\MySubKey@Value)

Para obtener el valor predeterminado de la subclave, omita Value.

$(registry:Hive\MyKey\MySubKey)

Este valor del Registro puede usarse para inicializar una propiedad de compilación. Por ejemplo, para crear una propiedad de compilación que represente la página principal del explorador web de Visual Studio, use este código:

<PropertyGroup>
  <VisualStudioWebBrowserHomePage>
    $(registry:HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0\WebBrowser@HomePage)
  </VisualStudioWebBrowserHomePage>
<PropertyGroup>

Advertencia

En la versión del SDK de .NET para MSBuild (dotnet build), no se admiten las propiedades del Registro.

Crear propiedades durante la ejecución

A las propiedades ubicadas fuera de los elementos Target se les asignan valores durante la fase de evaluación de una compilación. En la siguiente fase de la ejecución, se pueden crear o modificar propiedades como se indica a continuación:

  • Cualquier tarea puede emitir una propiedad. Para emitir una propiedad, el elemento Task debe tener un elemento Output secundario que tenga un atributo PropertyName.

  • La tarea CreateProperty puede emitir una propiedad. (en desuso).

  • Los elementos Target pueden contener elementos PropertyGroup que pueden contener declaraciones de propiedad.

Propiedades globales

MSBuild permite establecer propiedades en la línea de comandos mediante el modificador -property (o -p). Los valores de estas propiedades globales reemplazan los valores de propiedad establecidos en el archivo del proyecto. Esto incluye las propiedades de entorno pero no las propiedades reservadas ya que estas no se pueden cambiar.

En el siguiente ejemplo, se establece la propiedad global Configuration en DEBUG.

msbuild.exe MyProj.proj -p:Configuration=DEBUG

Las propiedades globales también se pueden establecer o modificar para proyectos secundarios en una compilación de varios proyectos mediante el atributo Properties de la tarea de MSBuild. Las propiedades globales también se reenvían a los proyectos secundarios, a menos que se use el atributo RemoveProperties de la tarea MSBuild para especificar la lista de propiedades que no se reenvían. Para más información, consulte Tarea de MSBuild.

Propiedades locales

Las propiedades locales se pueden restablecer en un proyecto. Las propiedades globales no. Cuando se establece una propiedad local desde la línea de comandos con la opción -p, el valor del archivo del proyecto tiene prioridad sobre la línea de comandos.

Especifique una propiedad local mediante el atributo TreatAsLocalProperty en una etiqueta de proyecto.

El código siguiente especifica que dos propiedades son locales:

<Project Sdk="Microsoft.Net.Sdk" TreatAsLocalProperty="Prop1;Prop2">

Las propiedades locales no se reenvían a proyectos secundarios en una compilación de varios proyectos. Si proporciona un valor en la línea de comandos con la opción -p, los proyectos secundarios reciben el valor de la propiedad global en lugar del valor local cambiado en el proyecto primario, pero el proyecto secundario (o cualquiera de sus importaciones) también puede cambiarlo con su propio TreatAsLocalProperty.

Ejemplo con propiedades locales

En el siguiente ejemplo de código se muestra el efecto de TreatAsLocalProperty:

<!-- test1.proj -->
<Project TreatAsLocalProperty="TreatedAsLocalProp">
    <PropertyGroup>
        <TreatedAsLocalProp>LocalOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <Target Name="Go">
        <MSBuild Projects="$(MSBuildThisFileDirectory)\test2.proj" Targets="Go2" Properties="Inner=true" />
    </Target>

    <Target Name="Go2" BeforeTargets="Go">
        <Warning Text="TreatedAsLocalProp($(MSBuildThisFileName)): $(TreatedAsLocalProp)" />
    </Target>
</Project>
<!-- test2.proj -->
<Project TreatAsLocalProperty="TreatedAsLocalProp">
    <Target Name="Go2">
        <Warning Text="TreatedAsLocalProp($(MSBuildThisFileName)): $(TreatedAsLocalProp)" />
    </Target>
</Project>

Supongamos que compila la línea de comandos test1.proj y asigna a TreatedAsLocalProperty el valor global GlobalOverrideValue:

dotnet msbuild .\test1.proj -p:TreatedAsLocalProp=GlobalOverrideValue

La salida es como sigue:

test1.proj(11,9): warning : TreatedAsLocalProp(test): LocalOverrideValue
test2.proj(3,9): warning : TreatedAsLocalProp(test2): GlobalOverrideValue

El proyecto secundario hereda el valor global, pero el proyecto primario usa la propiedad establecida localmente.

Propiedades e importaciones locales

Cuando se usa el atributo TreatAsLocalProperty en el proyecto importado, el orden es importante al considerar qué valor obtiene la propiedad.

En el ejemplo de código siguiente se muestra el efecto de TreatAsLocalProperty en un proyecto importado:

<!-- importer.proj -->
<Project>
    <PropertyGroup>
        <TreatedAsLocalProp>FirstOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <Import Project="import.props" />

    <PropertyGroup>
        <TreatedAsLocalProp Condition=" '$(TrySecondOverride)' == 'true' ">SecondOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <Target Name="Go">
        <Warning Text="TreatedAsLocalProp($(MSBuildThisFileName)): $(TreatedAsLocalProp)" />
    </Target>
</Project>
<!-- import.proj -->
<Project TreatAsLocalProperty="TreatedAsLocalProp">
    <PropertyGroup>
        <TreatedAsLocalProp>ImportOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <!-- Here, TreatedAsLocalProp has the value "ImportOverrideValue"-->
</Project>

Supongamos que compila importer.proj y establece un valor global para TreatedAsLocalProp como se indica a continuación:

dotnet msbuild .\importer.proj -p:TreatedAsLocalProp=GlobalOverrideValue

La salida es la siguiente:

importer.proj(9,9): warning : TreatedAsLocalProp(importer.proj): GlobalOverrideValue

Ahora supongamos que compila con la propiedad TrySecondOverride para true:

dotnet msbuild .\importer.proj -p:TreatedAsLocalProp=GlobalOverrideValue -p:TrySecondOverride=true

La salida es la siguiente:

importer.proj(13,9): warning : TreatedAsLocalProp(importer.proj): SecondOverrideValue

En el ejemplo se muestra que la propiedad se trata como local después del proyecto importado donde se usó el atributo TreatAsLocalProperty, no solo dentro del archivo importado. El valor de la propiedad se ve afectado por el valor de invalidación global, pero solo antes del proyecto importado donde se usa TreatAsLocalProperty.

Para obtener más información, vea Elemento Project (MSBuild) y Cómo: Compilar los mismos archivos de código fuente con diferentes opciones.

Funciones de propiedad

A partir de .NET Framework versión 4, se pueden usar funciones de propiedad para evaluar los scripts de MSBuild. Se puede leer la hora del sistema, comparar cadenas, buscar coincidencias de expresiones regulares y realizar muchas otras acciones en el script de compilación sin usar tareas de MSBuild.

Se pueden usar métodos de tipo string (instancia) con cualquier valor de propiedad y se puede llamar a los métodos estáticos de muchas clases del sistema. Por ejemplo, se puede establecer una propiedad de compilación en la fecha de hoy de la manera siguiente:

<Today>$([System.DateTime]::Now.ToString("yyyy.MM.dd"))</Today>

Para obtener más información y una lista de las funciones de propiedad, vea Funciones de propiedad.

Almacenar XML en propiedades

Las propiedades pueden contener código XML arbitrario, que puede ayudar a pasar valores a las tareas o a mostrar información de registro. En el ejemplo siguiente se muestra la propiedad ConfigTemplate, que tiene un valor que contiene código XML y referencias a otras propiedades. MSBuild reemplaza dichas referencias con los respectivos valores de propiedad. Los valores de propiedad se asignan en el orden en que aparecen. Por consiguiente, en este ejemplo, $(MySupportedVersion), $(MyRequiredVersion)y $(MySafeMode) ya deben haberse definido.

<PropertyGroup>
    <ConfigTemplate>
        <Configuration>
            <Startup>
                <SupportedRuntime
                    ImageVersion="$(MySupportedVersion)"
                    Version="$(MySupportedVersion)"/>
                <RequiredRuntime
                    ImageVersion="$(MyRequiredVersion)"
                    Version="$(MyRequiredVersion)"
                    SafeMode="$(MySafeMode)"/>
            </Startup>
        </Configuration>
    </ConfigTemplate>
</PropertyGroup>