Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
867 views
in Technique[技术] by (71.8m points)

xml - TFS 2010/Code Metrics Integration, Automated Builds Fail, Code Metrics Don't Run

I'm trying to add an automatic post-build trigger to run NDepend (code metrics software) after an automated team build in TFS 2010.

NDepend's website provided code for integrating this capability, and so I have pasted their code into my .csproj file where they said for it to go, but I receive errors on the build.

The errors refer to two of the three "BuildStep" tags I have in the code snippet. The following two snippets are giving me errors:

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

and

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

However, this code snippet is NOT throwing up any problems:

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

I just don't understand why one works fine and a nearly identically laid out BuildStep tag does not. Is there something simple that I'm just overlooking?

EDIT: Here is how it looks all together, if this makes a difference:

  <Target Name="NDepend"  >
    <PropertyGroup>
      <NDPath>c:oolsNDependNDepend.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:oolsNDependNDepend.console.exe</NDPath>
      <NDProject>$(SolutionRoot)MainsrcMyProject.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>

EDIT: Added a bounty because I really need to get this going for my team.

EDIT: Included more specifics about the errors, I disguised the location/name of the file by "blah" for copyright reasons, I'm not sure if I'm technically able to release that info, so I am erring on the side of safe rather than sorry, but if you absolutely must know for the sake of fixing this problem, I'll see what I can do. The following errors were listed in the results of the failed team build as well as various other warnings, but these errors were the only ones that I could see that pertained to the NDepend XML code above.

The errors I get when I run the team build:

C:*Blah*.csproj (172): The "BuildStep" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with in the project file, or in the *.tasks files located in the "c:WindowsMicrosoft.NETFrameworkv4.0.30319" directory.

and

C:*Blah*.csproj (194): The "BuildStep" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with in the project file, or in the *.tasks files located in the "c:WindowsMicrosoft.NETFrameworkv4.0.30319" directory.

EDIT: I thought I had it running right, but it sill isn't building properly. It's still throwing up the errors above when I build, despite mimicking @Ewald's suggested XML below. I adjusted the property values of said code according to what I think should work as follows:

  <Target Name="NDepend"  >
    <PropertyGroup>
      <NDPath>c:oolsNDependNDepend.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>

However, I did try just putting this code in:

  <Target Name="NDepend"  >
    <PropertyGroup>
      <NDPath>c:oolsNDependNDepend.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>

And the automated build went fine, no errors, but the NDepend just didn't run like it was supposed to.

I'm beginning to wonder (after consultation with various other sub-questions) if there's some slight difference in the XML schema used in TFS2010 vs TFS2008 that is causing me to have these problems. So, with that in mind, does anyone know about any big differences in these schemas?

EDIT: Just keeping you all up to date with everything I've tried, I now tried this code:

<Target Name="AfterBuild">
    <PropertyGroup>
      <NDPath>c:oolsNDependNDepend.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>

and it produced a different error message, as follows:

C:*Blah*.csproj (179): The command ""c:oolsNDependNDepend.console.exe" "C:*Blah*SourcesMainMyProject.ndproj" /OutDir "C:*Blah*BinariesDebugNDepend" /InDirs "C:*Blah*BinariesDebug"" exited with code 1.

EDIT: The latest code I tried. This was (according to NDepend's site) the "built-in NDepend MSBuild task."

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

But I get this error:

C:*Blah*.csproj (180): The element beneath element is unrecognized.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I use the following lines of code to achieve additional build steps

<Target Name="Customization">
    <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Name="CallMyTarget" Message="Call my target" Condition="'$(IsDesktopBuild)'!='true'" >
        <Output TaskParameter="Id" PropertyName="CurrentBuildStepId" />
    </BuildStep>

    <CallTarget Targets="MyTarget" ContinueOnError="false"/>

    <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(CurrentBuildStepId)" Status="Succeeded" Condition="'$(IsDesktopBuild)'!='true'" />

    <OnError ExecuteTargets="FailStep"/>
</Target>

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...