新(“ sdk样式”)与旧项目格式的MsBuild条件

时间:2018-09-19 07:11:29

标签: visual-studio msbuild

我想编写一个msbuild“ include”(.props)文件,该文件将同时在新项目(“ sdk样式”)和旧项目中导入。

有没有办法找出将.props文件导入哪种类型的项目,以便可以在某种情况下使用?例如,

<PropertyGroup Condition="'$(ProjectType)'=='sdk'">
   <SomeProperty>SomeValue</SomeProperty>
</PropertyGroup>

4 个答案:

答案 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项目?

换句话说:

  • 提供了XML文件...
  • 完整路径位于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|&gt;)&lt;Project\s(([^&gt;]*?)\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|&gt;)&lt;Project\s(([^&gt;]*?)\s)?Sdk(\s*?)=(\s*?)"`))</_IsSdkProject>
</PropertyGroup>

然后,您可以在_IsSdkProject中使用TrueFalse的值Condition,如下所示:

<PropertyGroup Condition="'$(_IsSdkProject)'=='True'">
  <SomeProperty>SomeValue</SomeProperty>
</PropertyGroup>

正则表达式解释

在上述正则表达式中,<>字符已替换为XML实体(分别为&lt;&gt;)。原始正则表达式如下:

(?s-i)(^|\s|>)<Project\s(([^>]*?)\s)?Sdk(\s*?)=(\s*?)"

意思是:

  • single-line, case-sensitive mode中...
  • 在文件的开头,或者在空格字符之后,或者在>字符之后...
  • 找到文字字符串<Project ...
  • 然后是一个空格字符...
  • 然后,可选地,除了>以外的任意数量的任意其他字符,以及另一个空格字符...
  • 然后输入文字字符串Sdk ...
  • 然后,可选地,任意数量的空格字符...
  • 然后输入字符= ...
  • 然后,可选地,任意数量的空格字符...
  • 然后输入字符"

on regex101.com是一个更好的解释,同时还有在线测试仪,您可以在其中插入项目文件的内容并进行实时测试。该网站是为Javascript正则表达式制作的,它们的行为与.NET完全不同,但仍然非常有用。