TFS 2010 / integração de métricas de código, falha de compilações automatizadas, métricas de código não executadas

Estou tentando adicionar um gatilho pós-compilação automático para executar o NDepend (software de métricas de código) após uma compilação de equipe automatizada no TFS 2010.

O site da NDepend forneceu código para integrar esse recurso e, portanto, colei o código no meu arquivo .csproj onde eles pediram, mas recebo erros na compilação.

Os erros referem-se a duas das três marcas "BuildStep" que tenho no snippet de código. Os dois trechos a seguir estão me dando erros:

<BuildStep         
    TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
    BuildUri="$(BuildUri)"
    Message="Running NDepend analysis">
  <Output TaskParameter="Id" PropertyName="StepId" />
</BuildStep>

e

<BuildStep
   TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
   BuildUri="$(BuildUri)"
   Id="$(StepId)"
   Status="Failed" />

No entanto, esse trecho de código NÃO está apresentando problemas:

<BuildStep
   TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
   BuildUri="$(BuildUri)"
   Id="$(StepId)"
   Status="Succeeded" />

Só não entendo por que alguém funciona bem e uma tag BuildStep quase idêntica. Existe algo simples que estou apenas ignorando?

EDIT: Aqui está como fica tudo junto, se isso faz a diferença:

  <Target Name="NDepend"  >
    <PropertyGroup>
      <NDPath>c:\tools\NDepend\NDepend.console.exe</NDPath>
      <NDProject>$(SolutionDir)MyProject.ndproj</NDProject>
      <NDOut>$(TargetDir)NDepend</NDOut>
      <NDIn>$(TargetDir)</NDIn>
    </PropertyGroup>
    <Exec
      Command='"$(NDPath)" "$(NDProject)" /OutDir "$(NDOut)" /InDirs "$(NDIn)"'/>
  </Target>
  <Target Name="AfterBuild">
    <BuildStep         TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        BuildUri="$(BuildUri)"
        Message="Running NDepend analysis">
      <Output TaskParameter="Id" PropertyName="StepId" />
    </BuildStep>
    <PropertyGroup>
      <NDPath>c:\tools\NDepend\NDepend.console.exe</NDPath>
      <NDProject>$(SolutionRoot)\Main\src\MyProject.ndproj</NDProject>
      <NDOut>$(BinariesRoot)\NDepend</NDOut>
      <NDIn>$(BinariesRoot)\Release</NDIn>
    </PropertyGroup>
    <Exec
      Command='$(NDPath) "$(NDProject)" /OutDir "$(NDOut)" /InDirs "$(NDIn)"'/>
    <BuildStep
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        BuildUri="$(BuildUri)"
        Id="$(StepId)"
        Status="Succeeded" />
    <OnError ExecuteTargets="MarkBuildStepAsFailed" />
  </Target>

  <Target Name="MarkBuildStepAsFailed">
    <BuildStep
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        BuildUri="$(BuildUri)"
        Id="$(StepId)"
        Status="Failed" />
  </Target>

Edição: Adicionado uma recompensa, porque eu realmente preciso fazer isso para a minha equipe.

EDIT: Incluído mais detalhes sobre os erros, disfarcei o local / nome do arquivo por "blá" por motivos de direitos autorais, não tenho certeza se sou tecnicamente capaz de liberar essas informações, por isso estou errado ao lado de seguro em vez de desculpe, mas se você absolutamente precisa saber para corrigir esse problema, verei o que posso fazer. Os seguintes erros foram listados nos resultados da criação de equipes com falha, bem como em vários outros avisos, mas esses erros foram os únicos que eu pude ver que pertenciam ao código XML NDepend acima.

Os erros que recebo quando executo a criação da equipe:

C: * Blah * .csproj (172): A tarefa "BuildStep" não foi encontrada. Verifique o seguinte: 1.) O nome da tarefa no arquivo do projeto é igual ao nome da classe de tarefa. 2.) A classe de tarefa é "pública" e implementa a interface Microsoft.Build.Framework.ITask. 3.) A tarefa foi declarada corretamente no arquivo do projeto ou nos arquivos * .tasks localizados no diretório "c: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319".

e

C: * Blah * .csproj (194): A tarefa "BuildStep" não foi encontrada. Verifique o seguinte: 1.) O nome da tarefa no arquivo do projeto é igual ao nome da classe de tarefa. 2.) A classe de tarefa é "pública" e implementa a interface Microsoft.Build.Framework.ITask. 3.) A tarefa foi declarada corretamente no arquivo do projeto ou nos arquivos * .tasks localizados no diretório "c: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319".

Edição: Eu pensei que tinha funcionado direito, mas ainda não está construindo corretamente. Ele ainda está exibindo os erros acima quando eu construo, apesar de imitar o XML sugerido por @ Ewald abaixo. Eu ajustei os valores de propriedade do referido código de acordo com o que acho que deve funcionar da seguinte maneira:

  <Target Name="NDepend"  >
    <PropertyGroup>
      <NDPath>c:\tools\NDepend\NDepend.console.exe</NDPath>
      <NDProject>$(SolutionDir)MyProject.ndproj</NDProject>
      <NDOut>$(TargetDir)NDepend</NDOut>
      <NDIn>$(TargetDir)</NDIn>
    </PropertyGroup>
    <Exec
      Command='"$(NDPath)" "$(NDProject)" /OutDir "$(NDOut)" /InDirs "$(NDIn)"'/>
  </Target>

  <Target Name="AfterBuild">
    <BuildStep         
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        BuildUri="$(BuildUri)"
        Name="CallMyTarget"
        Message="Call My Target"
        Condition="'$(IsDesktopBuild)'!='true'">
      <Output TaskParameter="Id" PropertyName="StepId" />
    </BuildStep>
    <CallTarget Targets="NDepend" ContinueOnError="false"/>
    <BuildStep
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        BuildUri="$(BuildUri)"
        Id="$(StepId)"
        Status="Succeeded"
        Condition="'$(IsDesktopBuild)'!='true'" />
    <OnError ExecuteTargets="FailStep" />
  </Target>

  <Target Name="FailStep">
    <BuildStep
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        BuildUri="$(BuildUri)"
        Id="$(StepId)"
        Status="Failed"
        Condition="'$(IsDesktopBuild)'!='true'" />
  </Target>

No entanto, tentei colocar esse código em:

  <Target Name="NDepend"  >
    <PropertyGroup>
      <NDPath>c:\tools\NDepend\NDepend.console.exe</NDPath>
      <NDProject>$(SolutionDir)MyProject.ndproj</NDProject>
      <NDOut>$(TargetDir)NDepend</NDOut>
      <NDIn>$(TargetDir)</NDIn>
    </PropertyGroup>
    <Exec
      Command='"$(NDPath)" "$(NDProject)" /OutDir "$(NDOut)" /InDirs "$(NDIn)"'/>
  </Target>

E a construção automatizada correu bem, sem erros, mas o NDepend simplesmente não funcionou como deveria.

Estou começando a me perguntar (após consulta com várias outras questões) se há alguma pequena diferença no esquema XML usado no TFS2010 vs TFS2008 que está me causando esses problemas. Então, com isso em mente, alguém sabe sobre grandes diferenças nesses esquemas?

EDIT: Mantendo todos vocês atualizados com tudo que tentei, agora tentei este código:

<Target Name="AfterBuild">
    <PropertyGroup>
      <NDPath>c:\tools\NDepend\NDepend.console.exe</NDPath>
      <NDProject>$(SolutionDir)MyProject.ndproj</NDProject>
      <NDOut>$(TargetDir)NDepend</NDOut>
      <NDIn>$(TargetDir)</NDIn>
    </PropertyGroup>
    <Exec
      Command='"$(NDPath)" "$(NDProject)" /OutDir "$(NDOut)" /InDirs "$(NDIn)"'/>
</Target>

e produziu uma mensagem de erro diferente, da seguinte maneira:

C: * Blah * .csproj (179): O comando "" c: \ tools \ NDepend \ NDepend.console.exe "" C: * Blah * \ Sources \ Main \ MyProject.ndproj "/ OutDir" C: * Blah * \ Binaries \ Debug \ NDepend "/ InDirs" C: * Blah * \ Binaries \ Debug \ "" saiu com o código 1.

EDIT: O código mais recente que eu tentei. Essa foi (de acordo com o site da NDepend) a "tarefa interna do NDepend MSBuild".

<Target Name="AfterBuild">
    <PropertyGroup>
        <NDPath>c:\tools\NDepend\NDepend.console.exe</NDPath>
        <NDProject>$(SolutionDir)MyProject.ndproj</NDProject>
      </PropertyGroup>
      <UsingTask AssemblyFile="$(NDPath)\MSBuild\NDepend.Build.MSBuild.dll"
             TaskName="NDependTask" />
      <Target Name="NDepend"  >
        <NDependTask NDependConsoleExePath="$(NDPath)"
           ProjectFilePath="$(NDProject)" />
      </Target>
</Target>

Mas eu recebo este erro:

C: * Blah * .csproj (180): O elemento abaixo do elemento não é reconhecido.

questionAnswers(2)

yourAnswerToTheQuestion