3

During my build process I'm trying to copy a folder to the artifacts folder (\myserver\d$\TFBuild-Agent01\66\a).

So I put this in the .csproj file:

<Target Name="BeforeBuild">
  <Exec 
    Command="xcopy.exe  Databases &quot;$(Build.ArtifactStagingDirectory)\Databases&quot; /i /e /y /d" />
</Target>

This gets me

Error MSB4184: The expression """.ArtifactStagingDirectory" cannot be evaluated. Method 'System.String.ArtifactStagingDirectory' not found*

Everything I can find online says that $(Build.ArtifactStagingDirectory) is the way to do it. But it doesn't work.

Building with Visual Studio 2015 on TFS 2015

This doesn't work either:

<Exec 
Command="xcopy.exe  Databases &quot;$($Env:BUILD_ARTIFACTSTAGINGDIRECTORY)\Databases&quot; /i /e /y /d" />

The expression "$Env:BUILD_ARTIFACTSTAGINGDIRECTORY" cannot be evaluated.*

This doesn't error, but it looks like %BUILD_ARTIFACTSTAGINGDIRECTORY% gets replaced as an empty string:

 <Exec Command="xcopy.exe  Databases &quot;%BUILD_ARTIFACTSTAGINGDIRECTORY%\Databases&quot; /i /e /y /d" /> 
abatishchev
  • 98,240
  • 88
  • 296
  • 433
mhenry1384
  • 7,538
  • 5
  • 55
  • 74

2 Answers2

7

You have been mixing ways to access the build variables that the agent allows you. The syntax using $(some.variable) is interpreted by the agent itself. MSBuild has a similar looking syntax - $(PropertyName) - which does something different - it gives access to msbuild properties and does not allow for dots (.) in it's name, since you can use the dot to call functions on the value (e.g. $(OutputPath.Substring(3))).

When you want to reference build variables from MSBuild, you need to reference the environment variable that the agent sets. This is possible because MSBuild makes all environment variables accessible as global properties using its property syntax. The environment variable for Build.ArtifactStagingDirectory is BUILD_ARTIFACTSTAGINGDIRECTORY so you can use it in MSBuild using $(BUILD_ARTIFACTSTAGINGDIRECTORY).

I have been using it successfully in this script to default a property when run as part of a TFS/VSTS build (PublishBaseDir is a custom property used later):

<PropertyGroup>
  <!-- Default artifact staging directory when built via VSTS / TFS agent -->
  <PublishBaseDir Condition="'$(PublishBaseDir)' == '' and '$(BUILD_ARTIFACTSTAGINGDIRECTORY)' != '' ">$(BUILD_ARTIFACTSTAGINGDIRECTORY)</PublishBaseDir>

  <!-- If not built on a known agent, use a "publish" subdir next to this file -->
  <PublishBaseDir Condition="'$(PublishBaseDir)' == ''">$(MSBuildThisFileDirectory)publish\</PublishBaseDir>

  <!-- Normalize directory if set manually or through ENV var -->
  <PublishBaseDir Condition="!HasTrailingSlash('$(PublishBaseDir)')">$(PublishBaseDir)\</PublishBaseDir>
</PropertyGroup>
Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • Was looking everywhere for an example like this, thank you!. The docs themselves have examples in every other context and scenario EXCEPT the one most useful!! – Warren Jan 23 '20 at 16:31
0

OK, I guess that because I'm using Visual Studio to build my solution, I can't access $(Build.StagingDirectory) from the .csproj. However, it's being passed on the command line to the "Visual Studio Build" build step as a property:

/p:OutDir="$(Build.StagingDirectory)"

So that can be accessed by doing

<Exec Command="xcopy.exe  Databases &quot;$(OutDir)\Databases&quot; /i /e /y /d" />
mhenry1384
  • 7,538
  • 5
  • 55
  • 74
  • 1
    Not sure if your problem is solved now but in order to debug such cases the MSBuild Message task is useful: That way you see to what value it has really been set inside the csproj – ackh Jul 09 '17 at 10:18