在元数据值上使用Item函数

时间:2012-03-01 08:00:38

标签: msbuild

后台:我管理的是一个相当大的解决方案。每隔一段时间,人们就会在解决方案中为项目添加DLL引用,他们应该添加项目引用。我想在这种情况下发出警告。我想通过在他们的HintPath *中找到'bin \ debug'的所有引用来做到这一点。我知道引用是ItemGroup中的项目,元数据为“HintPath”。

我期待这样的事情发挥作用:

<Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)"
         Condition="%(Reference.HintPath).IndexOf('bin\debug') != -1"/>

然而,似乎我不能像这样使用字符串函数IndexOf。我尝试了上述的许多排列,没有成功。

  • 编辑:我知道这张支票不是全面的,但我只想减少诚实的错误。

3 个答案:

答案 0 :(得分:20)

使用MSBuild 4.0 Property Functions可以进行字符串比较:

<Target Name="AfterBuild">

  <Message Text="Checking reference... '%(Reference.HintPath)'" Importance="high" />

  <Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)"
            Condition="$([System.String]::new('%(Reference.HintPath)').Contains('\bin\$(Configuration)'))" />

</Target>

答案 1 :(得分:2)

首先不是你的语法对于调用函数是不正确的,它需要是:

   %(Reference.HintPath.IndexOf(...))       # Note: not supported by MSBuild

但是,MSBuild中的属性函数对项目元数据是not allowed,因此也无法帮助您。

你可以通过调用一个基本上为每个项目调用的单独目标来解决这个问题。

  <Target Name="CheckProjectReferences">
    <MSBuild 
      Projects="$(MSBuildProjectFullPath)"
      Properties="Identity=%(Reference.Identity);HintPath=%(Reference.HintPath)"
      Targets="_Warn"/>
  </Target>

  <Target Name="_Warn">
    <Warning Text="Reference $(Identity) should be a project reference. HintPath: $(HintPath)"
             Condition="$(HintPath.IndexOf('bin\debug')) != -1"/>
  </Target>
坦率地说,我不确定这是否足以捕获所有“违规行为”。例如,上述内容仅适用于bin\debug,但不适用于bin\Debug或其他功能相同的混合外壳变体。要查找它们,您需要调用IndexOf(string, StringComparison)重载,但只需执行:

   $(HintPath.IndexOf('bin\debug', System.StringComparison.OrdinalIgnoreCase))

无法正常工作,因为MSBuild重载决策会选择IndexOf(char, Int32)并给您出错:

  

MSB4184:无法计算表达式“”bin \ debug“.IndexOf(bin \ debug,System.StringComparison.OrdinalIgnoreCase)”。字符串必须只有一个字符长。

因此,您需要直接使用IndexOf(String, Int32, Int32, StringComparison)重载来说服它:

   $(HintPath.IndexOf('bin\debug', 0, 9, System.StringComparison.OrdinalIgnoreCase))

您可能还需要检查bin\Release或其他变体。我不确定这是否是找出引用应该是项目引用的最佳方法,但如果您知道(并且在某种程度上控制)您的环境,那么它可能是可行的。

答案 2 :(得分:0)

@Christian.K在他的分析中是正确的。另一个解决方案是使用&quot;强制类型字符串的重载用于引号:

<Warning 
  Text="..." 
  Condition="$(HintPath.IndexOf(&quot;bin\debug&quot;, System.StringComparison.OrdinalIgnoreCase)) != -1" />