我想编写一个msbuild“ include”(.props)文件,该文件将同时在新项目(“ sdk样式”)和旧项目中导入。
有没有办法找出将.props文件导入哪种类型的项目,以便可以在某种情况下使用?例如,
<PropertyGroup Condition="'$(ProjectType)'=='sdk'">
<SomeProperty>SomeValue</SomeProperty>
</PropertyGroup>
答案 0 :(得分:4)
我在项目中遇到了同样的需求。最初,我使用解决方案@wexman,但是我发现该变量不可靠。我考虑了打开csproj文件并使用正则表达式来查找sdk属性的方法,但是对我来说它太脆弱了-特别是考虑到sdk可以在元素或属性中指定。最终,我创建了一个启用了二进制日志记录(选项/bl
)的构建,并在构建SDK样式的项目时遍历了导入的各种文件。
我在props文件中发现了属性UsingMicrosoftNETSdk
,该属性设置为true
,当您使用SDK样式的项目时,该属性会自动导入Microsoft.Common.props
。这种自动导入(导致Directory.Build.props的自动导入,似乎是SDK风格项目最重要的定义特征之一,并且该属性的名称使它看起来像更容易粘住
所以最终我的解决方案是:
Condition="'$(UsingMicrosoftNETSdk)' == 'true'"
(或其反函数)作为确定使用哪种类型项目的可靠方法。
答案 1 :(得分:2)
我似乎找到了可行的解决方案。我正在检查Microsoft.NET.Sdk.Props中声明的属性$(_ PlatformWithoutConfigurationInference)。如果不为空,则将处理sdk样式的项目,如果为空,则为旧项目:
<Project>
<PropertyGroup>
<ProjectStyle Condition="'$(_PlatformWithoutConfigurationInference)'!=''">sdk</ProjectStyle>
<ProjectStyle Condition="'$(_PlatformWithoutConfigurationInference)'==''">legacy</ProjectStyle>
</PropertyGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Message Importance="High" Text="$(MsBuildProjectName) is a $(ProjectStyle) style project" />
</Target>
</Project>
答案 2 :(得分:0)
新(“ sdk样式”)与旧项目格式的MsBuild条件
没有直接解决此问题的方法。因为MSBuild / Visual Studio中没有这样的属性ProjectType
。
我想在这里提供一种解决方法,您可以检查它是否适合您。众所周知,在旧的项目格式中,通常会有文件AssemblyInfo.cs
,在新的“ sdk样式”项目格式中不存在。因此,我们可以使用Condition="Exists('$(ProjectDir)\Properties\AssemblyInfo.cs')"
来找出.props
文件导入到哪种类型的项目:
我的测试.props
文件的内容:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="Exists('$(ProjectDir)\Properties\AssemblyInfo.cs')">
<SomeProperty>SomeValue1</SomeProperty>
</PropertyGroup>
<PropertyGroup Condition="!Exists('$(ProjectDir)\Properties\AssemblyInfo.cs')">
<SomeProperty>SomeValue2</SomeProperty>
</PropertyGroup>
<Target Name="Test" AfterTargets="AfterBuild">
<Message Text="$(SomeProperty)"></Message>
</Target>
</Project>
希望这会有所帮助。
答案 3 :(得分:0)
虽然测试属性值(或缺少属性值)是在MSBuild中完成几乎所有事情的方法,但有时还有其他方法。
您如何知道当前的MSBuild项目是否是SDK项目?
换句话说:
MSBuildProjectFullPath
well-known property ... Project
... Sdk
属性?感谢MSBuild的property functions,您可以执行以下操作:
[System.IO.File]::ReadAllText
以字符串形式读取项目文件的内容; [System.Text.RegularExpressions.Regex]::IsMatch
测试具有Project
属性的Sdk
标签。<PropertyGroup> <_ProjectContents>$([System.IO.File]::ReadAllText(`$(MSBuildProjectFullPath)`))</_ProjectContents> <_SdkRegex>(?s-i)(^|\s|>)<Project\s(([^>]*?)\s)?Sdk(\s*?)=(\s*?)"</_SdkRegex> <_IsSdkProject>$([System.Text.RegularExpressions.Regex]::IsMatch(`$(_ProjectContents)`, `$(_SdkRegex)`))</_IsSdkProject> </PropertyGroup>
或者,如果您喜欢单线:
<PropertyGroup>
<_IsSdkProject>$([System.Text.RegularExpressions.Regex]::IsMatch(`$([System.IO.File]::ReadAllText(`$(MSBuildProjectFullPath)`))`, `(?s-i)(^|\s|>)<Project\s(([^>]*?)\s)?Sdk(\s*?)=(\s*?)"`))</_IsSdkProject>
</PropertyGroup>
然后,您可以在_IsSdkProject
中使用True
或False
的值Condition
,如下所示:
<PropertyGroup Condition="'$(_IsSdkProject)'=='True'">
<SomeProperty>SomeValue</SomeProperty>
</PropertyGroup>
正则表达式解释
在上述正则表达式中,<
和>
字符已替换为XML实体(分别为<
和>
)。原始正则表达式如下:
(?s-i)(^|\s|>)<Project\s(([^>]*?)\s)?Sdk(\s*?)=(\s*?)"
意思是:
>
字符之后... <Project
... >
以外的任意数量的任意其他字符,以及另一个空格字符... Sdk
... =
... "
on regex101.com是一个更好的解释,同时还有在线测试仪,您可以在其中插入项目文件的内容并进行实时测试。该网站是为Javascript正则表达式制作的,它们的行为与.NET完全不同,但仍然非常有用。