Funciones de propiedad

Las funciones de propiedad son llamadas a métodos de .NET que aparecen en las definiciones de propiedad de MSBuild. A diferencia de las tareas, las funciones de propiedad se pueden usar fuera de los destinos. Las funciones de propiedad se evalúan cada vez que se expanden las propiedades o los elementos. Por lo tanto, para las propiedades y elementos que no están en ningún destino, las funciones de propiedad se evalúan antes de que se ejecute cualquier destino. En el caso de los grupos de propiedades y los grupos de elementos dentro de los destinos, las funciones de propiedad se evalúan cuando se evalúa el destino.

Se puede leer la hora del sistema, comparar cadenas, buscar coincidencias de expresiones regulares y realizar otras acciones en el script de compilación sin usar tareas de MSBuild. MSBuild intentará convertir la cadena en números y los números en cadena, y realizar otras conversiones que sean necesarias.

Los valores de cadena devueltos por las funciones de propiedad tienen caracteres especiales con secuencia de escape. Si quiere que el valor se considere como si se hubiese implementado directamente en el archivo del proyecto, use $([MSBuild]::Unescape()) para quitar las secuencias de escape de los caracteres especiales.

Sintaxis de las funciones de propiedad

Hay tres tipos de funciones de propiedad, cada una con una sintaxis diferente:

  • Funciones de propiedad de cadena (instancia)
  • Funciones de propiedad estáticas
  • Funciones de propiedad de MSBuild

Funciones de propiedad de cadena

Todos los valores de las funciones compiladas son solo valores de cadena. Puede usar los métodos de cadena (instancia) para operar en cualquier valor de propiedad. Por ejemplo, puede usar este código para extraer el nombre de unidad (los primeros tres caracteres) de una propiedad de compilación que representa una ruta completa:

$(ProjectOutputFolder.Substring(0,3))

Funciones de propiedad estáticas

En el script de compilación, puede acceder a las propiedades y método estáticos de muchas clases del sistema. Para obtener el valor de una propiedad estática, utilice la sintaxis siguiente, donde Class es el nombre de la clase del sistema y Property es el nombre de la propiedad.

$([Class]::Property)

Por ejemplo, puede usar el código siguiente para establecer una propiedad de compilación en la fecha y hora actuales.

<Today>$([System.DateTime]::Now)</Today>

Para llamar a un método estático, utilice la sintaxis siguiente, donde Class es el nombre de la clase del sistema, Method es el nombre del método y (Parameters) es la lista de parámetros del método:

$([Class]::Method(Parameters))

Por ejemplo, para establecer una propiedad de compilación en un nuevo GUID, puede usar este script:

<NewGuid>$([System.Guid]::NewGuid())</NewGuid>

En las funciones de propiedad estáticas, puede usar cualquier propiedad o método estático públicos de estas clases del sistema:

Además, puede usar los siguientes métodos y propiedades estáticos:

Funciones de la propiedad System.OperatingSystem

Las funciones de la propiedad System.OperatingSystem devuelven información sobre el sistema operativo en el que se ejecuta MSBuild. Por ejemplo, si el destino del proyecto es Linux y lo compila en macOS, las funciones de la propiedad devolverán información sobre macOS.

Si MSBuild se ejecuta en .NET (dotnet build), todos los métodos estáticos de la clase System.OperatingSystem se podrán llamar como funciones de una propiedad estática.

Si MSBuild se ejecuta en .NET Framework (MSBuild.exe), solo se pueden llamar a los métodos siguientes de System.OperatingSystem como funciones de una propiedad estática. MSBuild los implementa internamente porque System.OperatingSystem no los define en .NET Framework. No se puede llamar a los métodos de los sistemas operativos para los que no hay ningún SDK de .NET, como System.OperatingSystem::IsTvOS.

En el ejemplo siguiente se muestra el uso de estas funciones de propiedad.

<IsWindows>$([System.OperatingSystem]::IsWindows())</IsWindows>

Llamada a métodos de instancia en propiedades estáticas

Si accede a una propiedad estática que devuelve una instancia de objeto, puede invocar los métodos de instancia de ese objeto. Para llamar a un método de instancia, utilice la sintaxis siguiente, donde Class es el nombre de la clase del sistema, Property es el nombre de la propiedad, Method es el nombre del método y (Parameters) es la lista de parámetros del método:

$([Class]::Property.Method(Parameters))

El nombre de la clase debe ser completo en el espacio de nombres.

Por ejemplo, puede usar el código siguiente para establecer una propiedad de compilación en la fecha de hoy.

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

Funciones de propiedad de MSBuild

Puede acceder a varios métodos estáticos de su compilación para proporcionar compatibilidad con operadores aritméticos, lógicos bit a bit y caracteres de escape. Para acceder a estos métodos, utilice la sintaxis siguiente, donde Method es el nombre del método y (Parameters) es la lista de parámetros del método.

$([MSBuild]::Method(Parameters))

Por ejemplo, para sumar dos propiedades que tienen valores numéricos, use el código siguiente.

$([MSBuild]::Add($(NumberOne), $(NumberTwo)))

Esta es una lista de las funciones de propiedad de MSBuild:

Signatura de función Descripción
double Add(double a, double b) Suma dos valores double.
long Add(long a, long b) Suma dos valores long.
double Subtract(double a, double b) Resta dos valores double.
long Subtract(long a, long b) Resta dos valores long.
double Multiply(double a, double b) Multiplica dos valores double.
long Multiply(long a, long b) Multiplica dos valores long.
double Divide(double a, double b) Divide dos valores double.
long Divide(long a, long b) Divide dos valores long.
double Modulo(double a, double b) Realiza la operación de módulo en dos valores double.
long Modulo(long a, long b) Realiza la operación de módulo en dos valores long.
string Escape(string unescaped) Aplica un escape a la cadena según las reglas de escape de MSBuild.
string Unescape(string escaped) Elimina el escape de la cadena según las reglas de escape de MSBuild.
int BitwiseOr(int first, int second) Realiza una operación OR bit a bit en el primero y el segundo (primero | segundo).
int BitwiseAnd(int first, int second) Realiza una operación AND bit a bit en el primero y el segundo (primero & segundo).
int BitwiseXor(int first, int second) Realiza una operación XOR bit a bit en el primero y el segundo (primero ^ segundo).
int BitwiseNot(int first) Realiza una operación NOT bit a bit (~first).
bool IsOsPlatform(string platformString) Especifica si la plataforma del sistema operativo actual es platformString. platformString debe ser un miembro de OSPlatform.
bool IsOSUnixLike() True si el sistema operativo actual es un sistema Unix.
string NormalizePath(params string[] path) Obtiene la ruta de acceso completa con formato canónico de la ruta proporcionada y garantiza que contiene los caracteres separadores de directorio correctos para el sistema operativo actual.
string NormalizeDirectory(params string[] path) Obtiene la ruta de acceso completa con formato canónico del directorio proporcionado y garantiza que contiene los caracteres separadores de directorio correctos para el sistema operativo actual mientras garantiza que tiene una barra diagonal final.
string EnsureTrailingSlash(string path) Si la ruta de acceso proporcionada no tiene una barra diagonal final, entonces agrega una. Si la ruta es una cadena vacía, no la modifica.
string GetPathOfFileAbove(string file, string startingDirectory) Busca y devuelve la ruta de acceso completa a un archivo en la estructura de directorios en la ubicación del archivo de compilación actual, y por encima de ella, o en función de startingDirectory, si se especifica.
string GetDirectoryNameOfFileAbove(string startingDirectory, string fileName) Busca y devuelve el directorio de un archivo en el directorio especificado o en una ubicación de la estructura de directorios por encima de ese directorio.
string MakeRelative(string basePath, string path) Hace que path sea relativo a basePath. basePath debe ser un directorio absoluto. Si path no puede ser relativo, se devuelve textualmente. Similar a Uri.MakeRelativeUri.
string ValueOrDefault(string conditionValue, string defaultValue) Devuelve la cadena del parámetro defaultValue solo si el parámetro conditionValue está vacío; de lo contrario, devuelve el valor conditionValue.
string ConvertToBase64(string toEncode) Devuelve la cadena después de convertir todos los bytes en base 64 (caracteres alfanuméricos más + y /), terminando en uno o dos =.
string ConvertFromBase64(string toDecode) Devuelve la cadena después de convertirla de base 64 (caracteres alfanuméricos más + y /), terminando en uno o dos =.

Funciones de propiedad anidadas

Puede combinar funciones de propiedad para formar funciones más complejas, tal como se muestra en el ejemplo siguiente:

$([MSBuild]::BitwiseAnd(32, $([System.IO.File]::GetAttributes(tempFile))))

En este ejemplo se devuelve el valor de FileAttributes.Archivebits (32 o 0) del archivo que da la ruta de acceso tempFile. Observe que los valores de datos enumerados no pueden aparecer por nombre en algunos contextos. En el ejemplo anterior, se debe usar el valor numérico (32) en su lugar. En otros casos, en función de las expectativas del método llamado, se debe usar el valor de los datos de enumeración. En el ejemplo siguiente, el valor de enumeración RegexOptions.ECMAScript debe usarse porque un valor numérico no se puede convertir como espera este método.

<PropertyGroup>
    <GitVersionHeightWithOffset>$([System.Text.RegularExpressions.Regex]::Replace("$(PrereleaseVersion)", "^.*?(\d+)$", "$1", "System.Text.RegularExpressions.RegexOptions.ECMAScript"))</GitVersionHeightWithOffset>
</PropertyGroup>

En las funciones de propiedad anidadas también pueden aparecer metadatos. Para obtener más información, consulte Procesamiento por lotes.

DoesTaskHostExist de MSBuild

La función de propiedad DoesTaskHostExist de MSBuild devuelve si actualmente hay instalado un host de tareas para el tiempo de ejecución y los valores de arquitectura especificados.

Esta función de propiedad tiene la sintaxis siguiente:

$([MSBuild]::DoesTaskHostExist(string theRuntime, string theArchitecture))

MSBuild EnsureTrailingSlash

La función de propiedad EnsureTrailingSlash de MSBuild agrega una barra diagonal final, si todavía no existe.

Esta función de propiedad tiene la sintaxis siguiente:

$([MSBuild]::EnsureTrailingSlash('$(PathProperty)'))

GetDirectoryNameOfFileAbove de MSBuild

La función de propiedad GetDirectoryNameOfFileAbove de MSBuild busca hacia arriba un directorio que contenga el archivo especificado, empezando por el directorio indicado (incluido este). Devuelve la ruta de acceso completa del directorio más cercano que contiene el archivo si se encuentra; en caso contrario, devuelve una cadena vacía.

Esta función de propiedad tiene la sintaxis siguiente:

$([MSBuild]::GetDirectoryNameOfFileAbove(string startingDirectory, string fileName))

En este ejemplo se muestra cómo se importa el archivo EnlistmentInfo.props más cercano en la carpeta actual o por encima de esta, solo si se encuentra una coincidencia:

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), EnlistmentInfo.props))' != '' " />

Tenga en cuenta que este ejemplo se puede escribir de forma más concisa si se usa en su lugar la función GetPathOfFileAbove:

<Import Project="$([MSBuild]::GetPathOfFileAbove(EnlistmentInfo.props))" Condition=" '$([MSBuild]::GetPathOfFileAbove(EnlistmentInfo.props))' != '' " />

MSBuild GetPathOfFileAbove

La función de propiedad GetPathOfFileAbove de MSBuild busca hacia arriba un directorio que contenga el archivo especificado, empezando por el directorio indicado (incluido este). Devuelve la ruta de acceso completa del archivo coincidente más cercano si se encuentra; en caso contrario, devuelve una cadena vacía.

Esta función de propiedad tiene la sintaxis siguiente:

$([MSBuild]::GetPathOfFileAbove(string file, [string startingDirectory]))

Aquí, file es el nombre del archivo que se va a buscar y startingDirectory es un directorio opcional en el que se inicia la búsqueda. De forma predeterminada, la búsqueda se iniciará en el propio directorio del archivo actual.

En este ejemplo se muestra cómo se importa un archivo denominado dir.props en el directorio actual o por encima de este, solo si se encuentra una coincidencia:

<Import Project="$([MSBuild]::GetPathOfFileAbove(dir.props))" Condition=" '$([MSBuild]::GetPathOfFileAbove(dir.props))' != '' " />

Es funcionalmente equivalente a:

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))' != '' " />

Aun así, a veces es necesario iniciar la búsqueda en el directorio primario para evitar que coincida con el archivo actual. En este ejemplo se muestra cómo un archivo Directory.Build.props puede importar el archivo Directory.Build.props más cercano en un nivel estrictamente superior del árbol, sin importarse a sí mismo de forma recursiva:

<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />

Es funcionalmente equivalente a:

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildThisFileDirectory)../', 'Directory.Build.props'))/Directory.Build.props" />

GetRegistryValue de MSBuild

La función de propiedad GetRegistryValue de MSBuild devuelve el valor de una clave de registro. Esta función toma dos argumentos, el nombre de clave y el nombre de valor, y devuelve el valor del Registro. Si no especifica un nombre de valor, se devuelve el valor predeterminado.

En los ejemplos siguientes se muestra cómo usar esta función:

$([MSBuild]::GetRegistryValue(`HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\Debugger`, ``))                                  // default value
$([MSBuild]::GetRegistryValue(`HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\Debugger`, `SymbolCacheDir`))
$([MSBuild]::GetRegistryValue(`HKEY_LOCAL_MACHINE\SOFTWARE\(SampleName)`, `(SampleValue)`))             // parens in name and value

Advertencia

En la versión del SDK de .NET para MSBuild (dotnet build), esta función no se admite.

GetRegistryValueFromView de MSBuild

La función de propiedad GetRegistryValueFromView de MSBuild obtiene datos del Registro del sistema dada la clave del Registro, el valor y una o varias vistas del Registro ordenadas. La clave y el valor se buscan en cada vista del Registro por orden hasta que se encuentran.

La sintaxis de esta función de propiedad es:

[MSBuild]::GetRegistryValueFromView(string keyName, string valueName, object defaultValue, params object[] views)

El sistema operativo Windows de 64 bits mantiene una clave del Registro HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node que presenta una vista del Registro HKEY_LOCAL_MACHINE\SOFTWARE para aplicaciones de 32 bits.

De forma predeterminada, una aplicación de 32 bits que se ejecuta en WOW64 accede a la vista del Registro de 32 bits, y una aplicación de 64 bits accede a la vista del Registro de 64 bits.

Están disponibles las siguientes vistas del Registro:

Vista del Registro Definición
RegistryView.Registry32 La vista del Registro para aplicaciones de 32 bits.
RegistryView.Registry64 La vista del Registro para aplicaciones de 64 bits.
RegistryView.Default La vista del Registro que coincide con el proceso donde se está ejecutando la aplicación.

A continuación se muestra un ejemplo.

$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Silverlight\v3.0\ReferenceAssemblies', 'SLRuntimeInstallPath', null, RegistryView.Registry64, RegistryView.Registry32))

obtiene los datos de SLRuntimeInstallPath de la clave ReferenceAssemblies, y busca primero en la vista del Registro de 64 bits y, después, en la vista del Registro de 32 bits.

Advertencia

En la versión del SDK de .NET para MSBuild (dotnet build), esta función no se admite.

MakeRelative de MSBuild

La función de propiedad MakeRelative de MSBuild devuelve la ruta de acceso relativa de la segunda ruta de acceso, relativa a la primera ruta de acceso. Cada ruta de acceso puede ser un archivo o una carpeta.

Esta función de propiedad tiene la sintaxis siguiente:

$([MSBuild]::MakeRelative($(FileOrFolderPath1), $(FileOrFolderPath2)))

El código siguiente es un ejemplo de esta sintaxis.

<PropertyGroup>
    <Path1>c:\users\</Path1>
    <Path2>c:\users\username\</Path2>
</PropertyGroup>

<Target Name = "Go">
    <Message Text ="$([MSBuild]::MakeRelative($(Path1), $(Path2)))" />
    <Message Text ="$([MSBuild]::MakeRelative($(Path2), $(Path1)))" />
</Target>

<!--
Output:
   username\
   ..\
-->

MSBuild StableStringHash

La función de propiedad StableStringHash de MSBuild acepta un argumento de cadena y devuelve un código hash que se garantiza que sea estable, lo que significa que siempre se devuelve el mismo código para la misma entrada de cadena. El hash devuelto es el mismo, independientemente de que se usen MSBuild o dotnet build, y es estable en la arquitectura de la plataforma, a diferencia del método GetHashCode de .NET . No se garantiza que sea estable entre diferentes versiones de MSBuild.

Esta función está disponible tanto en MSBuild 16.9.0 como en las versiones posteriores.

En el ejemplo siguiente se muestra cómo usar esta función.

<Project>
   <PropertyGroup>
      <MyHash>$([MSBuild]::StableStringHash("test1"))</MyHash>
   </PropertyGroup>

   <Target Name="WriteHash" AfterTargets="Build">
      <Message Text="Hash: $(MyHash)"/>
   </Target>
</Project>

A partir de la versión 17.10.0 de MSBuild, esta función acepta el segundo argumento opcional que solicita que se use el algoritmo de hash:

<Project>
   <PropertyGroup>
      <MyHash>$([MSBuild]::StableStringHash("test1", "Sha256"))</MyHash>
   </PropertyGroup>

   <Target Name="WriteHash" AfterTargets="Build">
      <Message Text="Hash: $(MyHash)"/>
   </Target>
</Project>

El segundo argumento no distingue entre mayúsculas y minúsculas y actualmente admite los siguientes valores:

  • Heredado: conserva la misma acción de llamar a la función sin el segundo argumento. Devuelve un número entero de 32 bits con signo con propiedades similares a string.GetHashCode.
  • Fnv1a32bit: devuelve un número entero de 32 bits con signo que representa un hash Fowler–Noll–Vo de la versión "1a" de la cadena en cuestión.
  • Fnv1a64bit: devuelve un número entero de 64 bits con signo que representa un hash Fowler–Noll–Vo de la versión "1a" de la cadena en cuestión.
  • Sha256: devuelve una cadena hexadecimal sin prefijo que representa un hash SHA256 de la cadena en cuestión.

ValueOrDefault de MSBuild

La función de propiedad ValueOrDefault de MSBuild devuelve el primer argumento, a menos que sea nulo o vacío. Si el primer argumento es nulo o vacío, la función devuelve el segundo argumento.

En el ejemplo siguiente se muestra cómo usar esta función.

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

    <PropertyGroup>
        <Value1>$([MSBuild]::ValueOrDefault('$(UndefinedValue)', 'a'))</Value1>
        <Value2>$([MSBuild]::ValueOrDefault('b', '$(Value1)'))</Value2>
    </PropertyGroup>

    <Target Name="MyTarget">
        <Message Text="Value1 = $(Value1)" />
        <Message Text="Value2 = $(Value2)" />
    </Target>
</Project>

<!--
Output:
  Value1 = a
  Value2 = b
-->

Funciones TargetFramework y TargetPlatform de MSBuild

En MSBuild 16.7 y versiones posteriores se definen varias funciones para controlar las propiedades TargetFramework y TargetPlatform.

Signatura de función Descripción
GetTargetFrameworkIdentifier(string targetFramework) Analice TargetFrameworkIdentifier desde TargetFramework.
GetTargetFrameworkVersion(string targetFramework, int versionPartCount) Analice TargetFrameworkVersion desde TargetFramework.
GetTargetPlatformIdentifier(string targetFramework) Analice TargetPlatformIdentifier desde TargetFramework.
GetTargetPlatformVersion(string targetFramework, int versionPartCount) Analice TargetPlatformVersion desde TargetFramework.
IsTargetFrameworkCompatible(string targetFrameworkTarget, string targetFrameworkCandidate) Devuelve "True" si la plataforma de destino candidata (segundo argumento) es compatible con la plataforma de destino indicada por el primer argumento y "False" no lo es.

El parámetro versionPartCount de GetTargetFrameworkVersion y GetTargetPlatformVersion tiene un valor predeterminado de 2.

En el ejemplo siguiente se muestra cómo se usan estas funciones.

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

    <PropertyGroup>
        <Value1>$([MSBuild]::GetTargetFrameworkIdentifier('net5.0-windows7.0'))</Value1>
        <Value2>$([MSBuild]::GetTargetFrameworkVersion('net5.0-windows7.0'))</Value2>
        <Value3>$([MSBuild]::GetTargetPlatformIdentifier('net5.0-windows7.0'))</Value3>
        <Value4>$([MSBuild]::GetTargetPlatformVersion('net5.0-windows7.0'))</Value4>
        <Value5>$([MSBuild]::IsTargetFrameworkCompatible('net5.0-windows', 'net5.0'))</Value5>
        <Value6>$([MSBuild]::IsTargetFrameworkCompatible('net5.0', 'net6.0'))</Value6>
        <Value7>$([MSBuild]::IsTargetFrameworkCompatible('net5.0', 'net8.0'))</Value7>
    </PropertyGroup>

    <Target Name="MyTarget">
        <Message Text="Value1 = $(Value1)" />
        <Message Text="Value2 = $(Value2)" />
        <Message Text="Value3 = $(Value3)" />
        <Message Text="Value4 = $(Value4)" />
        <Message Text="Value5 = $(Value5)" />
        <Message Text="Value6 = $(Value6)" />
        <Message Text="Value7 = $(Value7)" />
    </Target>
</Project>
Value1 = .NETCoreApp
Value2 = 5.0
Value3 = windows
Value4 = 7.0
Value5 = True
Value6 = False
Value7 = False

Funciones de comparación de versiones de MSBuild

En MSBuild 16.5 y versiones posteriores se definen varias funciones para comparar cadenas que representan versiones.

Nota

Los operadores de comparación en condiciones pueden comparar cadenas que se pueden analizar como objetos System.Version, pero la comparación puede producir resultados inesperados. Se prefieren las funciones de propiedad.

Signatura de función Descripción
VersionEquals(string a, string b) Devuelve true si las versiones a y b son equivalentes según las reglas siguientes.
VersionGreaterThan(string a, string b) Devuelve true si la versión a es mayor que b según las reglas siguientes.
VersionGreaterThanOrEquals(string a, string b) Devuelve true si la versión a es mayor o igual que b según las reglas siguientes.
VersionLessThan(string a, string b) Devuelve true si la versión a es menor que b según las reglas siguientes.
VersionLessThanOrEquals(string a, string b) Devuelve true si la versión a es menor o igual que b según las reglas siguientes.
VersionNotEquals(string a, string b) Devuelve false si las versiones a y b son equivalentes según las reglas siguientes.

En estos métodos, las versiones se analizan como System.Version, con las excepciones siguientes:

  • Se omiten las instancias iniciales de v o V, lo que permite la comparación con $(TargetFrameworkVersion).

  • Se omite todo, desde el primer signo "-" o "+" hasta el final de la cadena de versión. Esto permite pasar versiones semánticas (semver), aunque el orden no es el mismo que el de semver. En su lugar, los especificadores de versión preliminar y los metadatos de compilación no tienen ningún peso de ordenación. Esto puede ser útil, por ejemplo, para activar una característica para >= x.y y hacer que se active en x.y.z-pre.

  • Las partes no especificadas son iguales que las partes de valor cero. (x == x.0 == x.0.0 == x.0.0.0).

  • No se permiten espacios en blanco en componentes enteros.

  • Solo es válida la versión principal (3 es igual a 3.0.0.0)

  • No se permite + como componente entero de inicio de sesión positivo (se trata como metadatos de semver y se omite).

Sugerencia

Las comparaciones de propiedades de TargetFramework suelen usar IsTargetFrameworkCompatible en lugar de extraer y comparar versiones. Esto permite comparar los objetos TargetFramework que varían tanto en TargetFrameworkIdentifier como en la versión.

Funciones de condiciones de MSBuild

Las funciones Exists y HasTrailingSlash no son funciones de propiedad. Están disponibles para su uso con el atributo Condition. Consulte Condiciones de MSBuild.