如何在MSBuild条件中定位所有.NET 5及以上版本?
.NET多目标框架MSBuild条件匹配问题
背景
当构建包含.NET 6.0和.NET Framework 4.7.2的多目标框架项目(项目文件中配置 <TargetFrameworks>net6.0;net472</TargetFrameworks>)时,可以通过MSBuild条件针对特定框架做定制化处理,比如:
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'"> Something </ItemGroup> <!-- 或者 --> <Target Name="MyUniqueTarget213243" BeforeTargets="Build"> <Message Importance="high" Text="Message for .net Framework" Condition="'$(TargetFramework)' == 'net472'" /> <Message Importance="high" Text="Message for .net 6 and higher" Condition="'$(TargetFramework)' == 'net6.0'" /> </Target>
这种写法仅对指定的特定框架版本有效,如果后续升级到.NET 8,或者遇到其他框架版本(比如.NET Framework 3.5)就会失效。目前旧框架固定为net472无需调整,但新版框架会不断更新(如8.0、10.0等),因此需要更通用的条件。
核心需求
需要设置MSBuild条件,实现:
- 匹配所有.NET 5及以上版本(如net5.0、net6.0、net8.0、net8.3)
- 排除.NET Core旧版本(如netcoreapp2.1)
- 排除.NET Framework 4.7.2(net472)
已尝试的方法及问题
以下是尝试过的写法,均存在问题:
<Message Importance="high" Text="Output Substring+Trim: '$(TargetFramework.Substring(3).Trim(`1234567890`))'" /> <Message Condition="'$(TargetFramework.Substring(3).Trim(`1234567890`))' == '.' " Importance="high" Text="ShowsIfConditionIsTrue" /> <!-- 问题:报错MSB4184,因为MSBuild在TargetFramework为空时仍会执行构建,导致Substring(3)索引越界;虽然可以搭配'$(TargetFramework)' != ''条件,但写法繁琐且不合理 --> <Message Importance="high" Text="Output Trim: '$(TargetFramework.Trim(`net1234567890`))'" /> <Message Condition="'$(TargetFramework.Trim(`net1234567890`))' == '.' " Importance="high" Text="ShowsIfConditionIsTrue" /> <!-- 问题:匹配逻辑不可靠 --> <Message Condition="'$(TargetFramework.Contains(`net6`))' == true" Importance="high" Text="ShowsIfConditionIsTrue" /> <!-- 问题:只能匹配单一框架版本,无法覆盖所有.NET 5+版本 --> <Message Condition="'$(new string[]{`net5.0`, `net6.0`}.Contains(TargetFramework))' == true" Importance="high" Text="ShowsIfConditionIsTrue" /> <!-- 问题:MSBuild不支持这种数组写法,无法计算表达式,只能用固定值匹配 --> <Message Condition="'$(TargetFramework)' != 'net472'" Importance="high" Text="ShowsIfConditionIsTrue" /> <!-- 问题:会误匹配net45、netcoreapp等不需要的框架版本 -->
解决方案
方法1:利用MSBuild内置属性精准判断
.NET 5+的TargetFrameworkIdentifier属性值为.NETCoreApp,且版本号≥5.0;而.NET Framework的TargetFrameworkIdentifier是.NETFramework,旧版.NET Core版本号<5.0。结合这些属性可以写出精准的条件:
<Target Name="CheckNet5Plus" BeforeTargets="Build"> <Message Importance="high" Text="当前为.NET 5及以上版本" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([System.Version]::Parse('$(TargetFrameworkVersion)').Major) >= 5 AND '$(TargetFramework)' != 'net472'" /> </Target>
说明:
TargetFrameworkIdentifier区分框架类型:.NET 5+和旧版.NET Core都是.NETCoreApp,.NET Framework是.NETFramework[System.Version]::Parse('$(TargetFrameworkVersion)').Major解析版本号的主版本,判断是否≥5- 额外排除
net472(虽然它的Identifier是.NETFramework,但可以明确排除)
方法2:基于正则表达式匹配框架标识
利用MSBuild的正则表达式功能,匹配以net开头且主版本≥5的框架标识,同时自动排除netcoreapp前缀的旧版:
<PropertyGroup> <!-- 定义正则表达式:匹配netX.Y或netX.Y.Z,其中X≥5 --> <Net5PlusRegex>^net([5-9]|\d{2,})\.\d+(\.\d+)?$</Net5PlusRegex> </PropertyGroup> <Target Name="CheckNet5PlusRegex" BeforeTargets="Build"> <Message Importance="high" Text="当前为.NET 5及以上版本" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '$(Net5PlusRegex)'))" /> </Target>
说明:
- 正则
^net([5-9]|\d{2,})\.\d+(\.\d+)?$确保:- 前缀是
net(而非netcoreapp) - 主版本号是5及以上(包括两位数如10)
- 格式符合
netX.Y或netX.Y.Z的版本规范
- 前缀是
内容的提问来源于stack exchange,提问作者Chrᴉz remembers Monica
相关产品推荐
相关产品推荐

