Share via


プロパティ関数

プロパティ関数は、MSBuild のプロパティ定義に含まれている .NET メソッドの呼び出しです。 タスクとは異なり、プロパティ関数はターゲットの外側でも使用できます。 プロパティ関数は、プロパティまたは項目が展開されるたびに評価されます。 そのため、ターゲットの外部にあるプロパティと項目の場合、プロパティ関数はターゲットが実行される前に評価されます。 ターゲットの内部にあるプロパティ グループと項目グループの場合、プロパティ関数はターゲットが評価されるときに評価されます。

MSBuild タスクを使用しなくても、システム時刻の読み取り、文字列の比較、正規表現の照合、その他の処理をビルド スクリプト内で実行できます。 MSBuild は、文字列を数値に、数値を文字列に変換しようと試みます。また、必要に応じて他の変換も実行します。

プロパティ関数から返される文字列値は、特殊文字がエスケープされます。 プロジェクト ファイルに直接配置した場合と同様に値を扱う場合は、$([MSBuild]::Unescape()) を使用して特殊文字のエスケープを解除します。

プロパティ関数の構文

次に 3 種類のプロパティ関数を示します。各関数には異なる構文があります。

  • 文字列 (インスタンス) プロパティ関数
  • 静的プロパティ関数
  • MSBuild プロパティ関数

文字列プロパティ関数

ビルド プロパティの値はすべて文字列値です。 文字列 (インスタンス) メソッドを使用してプロパティ値を操作できます。 たとえば、次のコードを使用して、完全パスを表すビルド プロパティからドライブ名 (最初の 3 文字) を抽出できます。

$(ProjectOutputFolder.Substring(0,3))

静的プロパティ関数

ビルド スクリプトで、各種システム クラスの静的プロパティおよびメソッドにアクセスできます。 静的プロパティの値を取得するには、次の構文を使用します。ここで、Class はシステム クラスの名前、Property はプロパティの名前です。

$([Class]::Property)

たとえば、次のコードを使用して、ビルド プロパティを現在の日付と時刻に設定します。

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

静的メソッドを呼び出すには、次の構文を使用します。ここで、Class はシステム クラスの名前、Method はメソッドの名前、(Parameters) はメソッドのパラメーター リストです。

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

たとえば、ビルド プロパティを新しい GUID に設定するには、次のスクリプトを使用できます。

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

静的プロパティ関数では、.NET Standard 2.0 で定義されている、あらゆるパブリック静的メソッドまたはプロパティを次のシステム クラスに使用できます。

Note

.NET Standard 2.0 で定義されていないメソッドとプロパティは、それらがサポートしている環境で MSBuild を使用する場合に使用できますが、すべての状況で使用できることを保証することはできません。 互換性の理由から使用を避けることをおすすめします。

さらに、次の静的メソッドおよびプロパティを使用できます。

System.OperatingSystem プロパティ関数

System.OperatingSystem プロパティ関数は、MSBuild が実行されているオペレーティング システムに関する情報を返します。 たとえば、プロジェクトが Linux を対象としていて、macOS 上でビルドした場合、このプロパティ関数は macOS に関する情報を返します。

.NET (dotnet build) 上で実行されている MSBuild の場合、System.OperatingSystem クラスのすべての静的メソッドは静的プロパティ関数として呼び出すことができます。

.NET Framework (MSBuild.exe) 上で実行されている MSBuild の場合、静的プロパティ関数として呼び出すことができるのは、次に示す System.OperatingSystem のメソッドのみです。 MSBuild はこれらを内部的に実装しています。なぜなら、.NET Framework 上の System.OperatingSystem には定義されていないからです。 .NET SDK がないオペレーティング システムのメソッド (たとえば System.OperatingSystem::IsTvOS) を呼び出すことはできません。

次の例は、これらのプロパティ関数の使用方法を示しています。

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

静的プロパティ上でインスタンス メソッドを呼び出す

オブジェクト インスタンスを返す静的プロパティにアクセスすると、そのオブジェクトのインスタンス メソッドを呼び出すことができます。 インスタンス メソッドを呼び出すには、次の構文を使用します。ここで、Class はシステム クラスの名前、Property はプロパティの名前、Method はメソッドの名前、(Parameters) はメソッドのパラメーター リストです。

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

クラスの名前は、名前空間を使用して完全修飾する必要があります。

たとえば、次のコードを使用して、ビルド プロパティを現在の日付 (今日) に設定します。

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

MSBuild プロパティ関数

ビルド内のいくつかの静的メソッドにアクセスすると、算術、ビットごとの論理、およびエスケープ文字のサポートが提供されます。 次の構文を使用して、これらのメソッドにアクセスします。ここで、Method はメソッドの名前、(Parameters) はメソッドのパラメーター リストです。

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

たとえば、数値を持つ 2 つのプロパティを合計するには、次のコードを使用します。

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

次に MSBuild プロパティ関数の一覧を示します。

関数シグネチャ 説明
double Add(double a, double b) 2 個の倍精度浮動小数点数を加算します。
long Add(long a, long b) 2 個の長整数を加算します。
double Subtract(double a, double b) 2 個の倍精度浮動小数点数を減算します。
long Subtract(long a, long b) 2 個の長整数を減算します。
double Multiply(double a, double b) 2 個の倍精度浮動小数点数を乗算します。
long Multiply(long a, long b) 2 個の長整数を乗算します。
double Divide(double a, double b) 2 個の倍精度浮動小数点数を除算します。
long Divide(long a, long b) 2 個の長整数を除算します。
double Modulo(double a, double b) 2 個の倍精度浮動小数点数を剰余します。
long Modulo(long a, long b) 2 個の長整数を剰余します。
string Escape(string unescaped) MSBuild のエスケープ ルールに従って文字列をエスケープします。
string Unescape(string escaped) MSBuild のエスケープ ルールに従って文字列をエスケープ解除します。
int BitwiseOr(int first, int second) 1 番目と 2 番目でビットごとの OR を実行します (first | second)。
int BitwiseAnd(int first, int second) 1 番目と 2 番目 (first & second) でビットごとの AND を実行します。
int BitwiseXor(int first, int second) 1 番目と 2 番目 (first ^ second) でビットごとの XOR を実行します。
int BitwiseNot(int first) ビットごとの NOT (~first) を実行します。
bool IsOsPlatform(string platformString) 現在の OS プラットフォームが platformString かどうかを指定します。 platformStringOSPlatform のメンバーである必要があります。
bool IsOSUnixLike() 現在の OS が Unix システムの場合は true です。
string NormalizePath(params string[] path) 指定されたパスの正規化された完全なパスを取得し、現在のオペレーティング システムの適切なディレクトリ区切り文字が含まれていることを確認します。
string NormalizeDirectory(params string[] path) 指定されたディレクトリの正規化された完全なパスを取得し、現在のオペレーティング システムの適切なディレクトリ区切り文字が含まれていて、末尾にスラッシュがあることを確認します。
string EnsureTrailingSlash(string path) 指定されたパスの末尾にスラッシュがない場合は、追加します。 パスが空の文字列の場合は変更されません。
string GetPathOfFileAbove(string file, string startingDirectory) 現在のビルド ファイルの場所またはその上にあるディレクトリ構造内のファイルへの完全なパスを検索して返します。指定した場合は startingDirectory が起点となります。
string GetDirectoryNameOfFileAbove(string startingDirectory, string fileName) 指定したディレクトリか、そのディレクトリの上のディレクトリ構造内の場所から、ファイルのディレクトリを探して返します。
string MakeRelative(string basePath, string path) pathbasePath に対して相対的にします。 basePath は絶対ディレクトリである必要があります。 path を相対にできない場合、verbatim が返されます。 Uri.MakeRelativeUri と似ています。
string ValueOrDefault(string conditionValue, string defaultValue) パラメーター conditionValue が空の場合にのみ、パラメーター defaultValue の文字列を返します。それ以外の場合は conditionValue の値を返します。
string ConvertToBase64(string toEncode) すべてのバイトを、末尾に 1 つまたは 2 つの = が付く base 64 (英数字と + および /) に変換した後、文字列を返します。
string ConvertFromBase64(string toDecode) 末尾に 1 つまたは 2 つの = が付く base 64 (英数字と + および /) から変換した後、文字列を返します。

入れ子になったプロパティ関数

次の例が示すように、プロパティ関数を組み合わせて、より複雑な関数を形成します。

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

この例では、FileAttributes.パス tempFile によって指定されたファイルの Archive ビット (32 または 0)。 一部のコンテキストでは、列挙されたデータ値を名前で表示できないことに注意してください。 上記の例では、代わりに数値 (32) を使用する必要があります。 それ以外の場合は、呼び出されるメソッドの予測に応じて、列挙データ値を使用する必要があります。 次の例では、列挙値 RegexOptions.ECMAScript を使う必要があります。このメソッドの予測に応じて数値を変換できないためです。

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

入れ子になったプロパティ関数では、メタデータも表示される可能性があります。 詳細については、「MSBuild バッチ」をご覧ください。

MSBuild の DoesTaskHostExist

MSBuild の DoesTaskHostExist プロパティ関数は、指定したランタイムとアーキテクチャ値に対してタスク ホストが現在インストールされているかどうかを返します。

このプロパティ関数には次の構文があります。

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

MSBuild EnsureTrailingSlash

MSBuild の EnsureTrailingSlash プロパティ関数は、末尾のスラッシュがないときにそれを追加します。

このプロパティ関数には次の構文があります。

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

MSBuild の GetDirectoryNameOfFileAbove

MSBuild GetDirectoryNameOfFileAbove プロパティ関数は、指定のファイルを含むディレクトリを探して上方向に検索します。指定のディレクトリで、または指定のディレクトリが含まれる位置から始めます。 ファイルが見つかった場合、ファイルを含む最も近いディレクトリの完全なパスを返します。それ以外の場合は空の文字列を返します。

このプロパティ関数には次の構文があります。

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

この例では、一致が見つかった場合にのみ、現在のフォルダーの中で、あるいはその上で最も近い EnlistmentInfo.props ファイルをインポートする方法を示しています。

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

この例は、代わりに GetPathOfFileAbove 関数を使用すると、より簡潔に記述できることにご留意ください。

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

MSBuild GetPathOfFileAbove

MSBuild GetPathOfFileAbove プロパティ関数は、指定のファイルを含むディレクトリを探して上方向に検索します。指定のディレクトリで、または指定のディレクトリが含まれる位置から始めます。 見つかった場合、近似一致ファイルの完全パスを、それ以外の場合は空の文字列を返します。

このプロパティ関数には次の構文があります。

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

file は検索対象のファイルの名前であり、startingDirectory は検索を始める任意のディレクトリです。 既定では、現在のファイル自体のディレクトリから検索が開始されます。

この例では、一致が見つかった場合にのみ、現在のディレクトリ内で、または現在のディレクトリの上で dir.props という名前のファイルをインポートする方法を示しています。

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

これは機能的には次と等しくなります。

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

ただし、現行ファイルとの一致を回避するため、親ディレクトリで検索を開始する必要があることがあります。 この例では、Directory.Build.props ファイルで、それ自体を再帰的にインポートすることなく、ツリーの厳密に高いレベルで最も近い Directory.Build.props ファイルをインポートするしくみを示します。

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

これは機能的には次と等しくなります。

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

MSBuild の GetRegistryValue

MSBuild の GetRegistryValue プロパティ関数は、レジストリ キーの値を返します。 この関数は、キー名と値の名前という 2 つの引数を取り、レジストリの値を返します。 値の名前を指定しない場合は、既定値が返されます。

この関数を使用する方法を次の例に示します。

$([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

警告

MSBuild の .NET SDK バージョン (dotnet build) では、この関数はサポートされていません。

MSBuild の GetRegistryValueFromView

MSBuild の GetRegistryValueFromView プロパティ関数は、レジストリ キー、値、および 1 つ以上の順序づけられたレジストリ ビューを含むシステム レジストリ データを取得します。 キーと値は見つかるまで各レジストリ ビューで順番に検索されます。

このプロパティ関数の構文を次に示します。

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

Windows 64 ビット オペレーティング システムは、HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node というレジストリ キーを保持しています。このキーは、32 ビット アプリケーションに対して HKEY_LOCAL_MACHINE\SOFTWARE というレジストリ ビューを提供します。

既定では、WOW64 で実行されている 32 ビット アプリケーションは 32 ビットのレジストリ ビューにアクセスし、64 ビット アプリケーションは 64 ビットのレジストリ ビューにアクセスします。

次のレジストリ ビューが使用できます。

レジストリ ビュー 定義
RegistryView.Registry32 32 ビット アプリケーションのレジストリ ビュー。
RegistryView.Registry64 64 ビット アプリケーションのレジストリ ビュー。
RegistryView.Default アプリケーションが実行されているプロセスに対応するレジストリ ビュー。

次に例を示します。

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

最初に 64 ビットのレジストリ ビュー、次に 32 ビットのレジストリ ビューを参照して、ReferenceAssemblies キーの SLRuntimeInstallPath データを取得します。

警告

MSBuild の .NET SDK バージョン (dotnet build) では、この関数はサポートされていません。

MSBuild の MakeRelative

MSBuild の MakeRelative プロパティ関数は、最初のパスに対する 2 番目のパスの相対パスを返します。 各パスはファイルまたはフォルダーです。

このプロパティ関数には次の構文があります。

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

次のコードはこの構文の例です。

<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

MSBuild の StableStringHash プロパティ関数は、文字列引数を受け取り、安定することが保証されたハッシュ コードを返します。つまり、同じ文字列入力に対しては常に同じコードが返されます。 返されるハッシュは、MSBuild と dotnet build のどちらを使っても同じであり、.NET メソッドの GetHashCode とは異なり、プラットフォーム アーキテクチャ全体で安定します。 異なる MSBuild バージョンをまたいで安定することは保証されません。

この関数は、MSBuild 16.9.0 以降で使用できます。

この関数を使用する方法を次の例に示します。

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

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

MSBuild バージョン 17.10.0 から、この関数では、2 番目の省略可能な引数を受け取り、使用するハッシュ アルゴリズムを要求します。

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

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

2 番目の引数では大文字と小文字が区別されず、現時点では以下の値がサポートされています。

  • Legacy - 2 番目の引数を指定せずに関数を呼び出す場合と同じ動作を維持します。 string.GetHashCode と同様の性質を持つ符号付き 32 ビット整数を返します。
  • Fnv1a32bit - 指定された文字列の Fowler-Noll-Vo ハッシュ バージョン '1a' のハッシュを表す符号付き 32 ビット整数を返します。
  • Fnv1a64bit - 指定された文字列の Fowler-Noll-Vo ハッシュ バージョン '1a' のハッシュを表す符号付き 64 ビット整数を返します。
  • Sha256 - 指定された文字列の SHA256 ハッシュを表す、プレフィックスなしの 16 進文字列を返します。

MSBuild の ValueOrDefault

MSBuild の ValueOrDefault プロパティ関数は、null または空でない限り、最初の引数を返します。 最初の引数が null または空の場合、関数は 2 番目の引数を返します。

この関数を使用する方法を次の例に示します。

<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
-->

MSBuild の TargetFramework と TargetPlatform の関数

MSBuild 16.7 以降には、TargetFramework と TargetPlatform のプロパティを処理するための関数がいくつか定義されています。

関数シグネチャ 説明
GetTargetFrameworkIdentifier(string targetFramework) TargetFramework から TargetFrameworkIdentifier を解析します。
GetTargetFrameworkVersion(string targetFramework, int versionPartCount) TargetFramework から TargetFrameworkVersion を解析します。
GetTargetPlatformIdentifier(string targetFramework) TargetFramework から TargetPlatformIdentifier を解析します。
GetTargetPlatformVersion(string targetFramework, int versionPartCount) TargetFramework から TargetPlatformVersion を解析します。
IsTargetFrameworkCompatible(string targetFrameworkTarget, string targetFrameworkCandidate) ターゲット フレームワーク候補 (2 番目の引数) が 1 番目の引数で示されているターゲット フレームワークと互換性がある場合は、"True" を返します。それ以外の場合は、False を返します。

GetTargetFrameworkVersionGetTargetPlatformVersionversionPartCount パラメーターの既定値は 2 です。

これらの関数を使用する方法を次の例に示します。

<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

MSBuild のバージョン比較関数

MSBuild 16.5 以降には、バージョンを表す文字列を比較する関数がいくつか定義されています。

注意

条件に比較演算子を使用して文字列を比較し、それを System.Version オブジェクトとして解析できますが、比較によって予期しない結果になる可能性があります。 プロパティ関数を使用することをお勧めします。

関数シグネチャ 説明
VersionEquals(string a, string b) 以下の規則に従ってバージョン ab が等しい場合は true を返します。
VersionGreaterThan(string a, string b) 以下の規則に従ってバージョン ab よりも大きい場合、true を返します。
VersionGreaterThanOrEquals(string a, string b) 以下の規則に従ってバージョン ab よりも大きいか等しい場合、true を返します。
VersionLessThan(string a, string b) 以下の規則に従ってバージョン ab よりも小さい場合、true を返します。
VersionLessThanOrEquals(string a, string b) 以下の規則に従ってバージョン ab よりも小さいか等しい場合、true を返します。
VersionNotEquals(string a, string b) 以下の規則に従ってバージョン ab が等しい場合は false を返します。

これらのメソッドでは、以下の例外を除き、バージョンは System.Version のように解析されます。

  • 先頭の v または V は無視されるので、$(TargetFrameworkVersion) と比較できます。

  • バージョン文字列の最初の '-' または '+' から末尾までのすべてが無視されます。 これにより、セマンティック バージョン (semver) を渡すことはできますが、その順序は semver と同じではありません。 その代わり、プレリリース指定子とビルド メタデータには並べ替えの重み付けがありません。 これは、たとえば、>= x.y の場合に機能を有効にして、x.y.z-pre の場合に起動する場合に役立ちます。

  • 指定されていない部分は、ゼロ値の部分と同じです。 (x == x.0 == x.0.0 == x.0.0.0)。

  • 整数部には空白を使用できません。

  • メジャー バージョンのみが有効です (33.0.0.0 と同じです)。

  • + は整数部の正符号としては使用できません (semver のメタデータとして扱われ、無視されます)。

ヒント

TargetFramework プロパティの比較には、一般的に、バージョンを抽出して比較するのではなく、IsTargetFrameworkCompatible を使用するようにします。 これにより、バージョンだけでなく TargetFrameworkIdentifier が異なる TargetFrameworks を比較することができます。

MSBuild 条件関数

関数 ExistsHasTrailingSlash は、プロパティ関数ではありません。 これらは、Condition 属性と一緒に使用することができます。 「MSBuild の条件」を参照してください。