TFS MSBuild copy command - tfs

The is my copy command:
<ItemGroup>
<SwfFiles Include="$(MSBuildProjectDirectory)\bin-release\**\*.*"/>
</ItemGroup>
<CallTarget Targets="CopyFilesToDropLocation"/>
<Target Name="CopyFilesToDropLocation">
<Copy
SourceFiles="#(SwfFiles)"
DestinationFiles="#(SwfFiles->'$(OutDir)_PublishedWebsites\PrismWeb\% (RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
I dont anything being copied to the destinaton. Any idea what am I doing wrong?

IS this space for hiding values ?
DestinationFiles="#(SwfFiles->'$(OutDir)_PublishedWebsites\PrismWeb\% [here] (RecursiveDir)%(Filename)%(Extension)')"/>
I tested this with some of my code
<Copy SourceFiles="#(SourceAllFiles)" DestinationFiles="% (RecursiveDir)%(Filename)%(Extension)'" />
This space will produce a copy that works, but it tries to copy the source to this destination:
% [nbSpaces](RecursiveDir)[this part of the metadata woks]

You should use the latest build template in TFS 2013.4. It has defined locations for executing PowerShell, one of which is post-build. Using Powershell is both easyer to debug and more future proof.

Related

ant copy task hanging when the source file is missing

In one of our build script, we have following simple copy task added ->
<copy todir="${targetdir}"
file="${sourcedir}/modules/glassfish.jaxb.xjc_1.0.0.0_2-1-12.jar"/>
This copy task started hanging when the glassfish jar name got changed (version upgrade which are not in our control) at the source location. I was expecting it to error out causing the build failure in that case. Actually at first I was not able to figure out at what particular step build was hanging. Then when I added "-debug" to the ant command and I realized its successfully completing a step prior to this copy task and still there was no trace of copy command that is hung. When I updated the new jar name, it worked fine and build was successful which proved that the copy task is hanging because of filename got changed. To make it easy to debug next time, I added an echo statement like below just prior to that copy task ->
<echo message="Copying glassfish jar to ${targetdir}.."/>
But I am still confused as to why it didn't give error with build failure? I am using Apache Ant version 1.7.1. Could this be a bug? How else I can avoid this situation in future with just the copy task (without using * in the jar name)? TIA
That worked for me. Well, didn't work for me. I got the error message. I am using Ant 1.8 and Ant 1.9.2. I didn't try it with Ant 1.7, but I doubt it's a bug.
Try to use the -v parameter in Ant:
$ ant -v target
And be prepared for a longwinded output. This will give you information what's going on with Ant, and may explain why it's freezing. There's a few things you could do: Use a fileset to specify the file.
<copy todir="${targetdir}">
<fileset dir="${sourcedir}/modules">
<include name="glassfish*.jar"/> <!-- Will catch any glassfish.jar -->
</fileset>
</copy>
Of course, if the file doesn't exist, you won't get an error or even a warning. However, a <fail/> before will detect the issue:
<fail message="missing file ${sourcedir}/modules/glassfish.jaxb.xjc_1.0.0.0_2-1-12.jar">
<condition>
<not>
<available
file="${sourcedir}/modules/glassfish.jaxb.xjc_1.0.0.0_2-1-12.jar"
type="file"/>
</not>
</condition>
</fail>
To force the build to quit, an alternative way
<available file="${sourcedir}/modules/glassfish.jaxb.xjc_1.0.0.0_2-1-12.jar"
property="glassfish.jaxb.xjc.jar.present"/>
<fail message="you message" unless="glassfish.jaxb.xjc.jar.present"/>
just a few lines less :)
If you want to dig into it, try this:
write a simple build file, which contains only one target with copy, and put it to the same place of your main build file.
<target name="test-copy">
<!-- here use an old (wrong) file name -->
<copy todir="${targetdir}"
file="${sourcedir}/modules/glassfish.jaxb.xjc_1.0.0.0_2-1-12.jar"/>
</target>
run it, check if it fails or hangs.
If this simple build file works, it's very possible that something else in your main build file is causing the bug.

Adding files to the bin directory at Build and Publish

I have two license files that I would like to include in my \bin directory both when I build and publish.
Both files are in the App_Data directory (their initial location doesn't matter, they just need to end up in the \bin) and have the following properties set:
Build Action = Content
Copy to Output Directory = Copy Always
They are in not the \bin when I build or publish.
What is wrong with my setup: the settings, the folders, the files, something else...?
UPDATE
I moved the files out of the App_Data directory and placed them in the project root and now they are copied to the \bin on build.
I've done this in a few projects by expanding my .csproject file slightly. The following code should be put directly beneath the Project node in your WebProject.csproj.
The AfterBuild target simply copies a set of files ("unreferenced DLLs" in this case) to the bin-folder when building normally from Visual Studio. The CustomCollectFiles basically do the same thing when deploying.
<PropertyGroup>
<UnreferencedDlls>..\lib\Unreferenced\**\*.dll</UnreferencedDlls>
</PropertyGroup>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="AfterBuild">
<Message Text="Copying unreferenced DLLs to bin" Importance="High" />
<CreateItem Include="$(UnreferencedDlls)">
<Output TaskParameter="Include" ItemName="_UnReferencedDLLs" />
</CreateItem>
<Copy SourceFiles="#(_UnReferencedDLLs)" DestinationFolder="bin\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CustomCollectFiles">
<Message Text="Publishing unreferenced DLLs" Importance="High" />
<ItemGroup>
<_CustomFiles Include="$(UnreferencedDlls)" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
The part you need to modify is basically the UnreferencedDlls node to match your folder structure. The **\*.dll part simply means "every DLL file at any level beneath here".
If you're using Visual Studio:
Show your file properties (Click on your file or Right-click on it then choose Properties)
At the Copy to Output Directory property choose Copy always or Copy if newer.
At build time, the file is going to be copied at the bin directory: Debug or Release...
not necessarily a direct answer, but I highly suggest not using the baked in "publish" mechanism, but rather wire up a build script (probably in powershell) that will do everything you need. It's really easy to hook into MSBuild as well as nUnit and also copy files and move them around.
POWERSHELL (rough) example.
# Get Directory Location
$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
# Build the application using MSBuild
cmd /c C:\Windows\Microsoft.NET\Framework\$v4_net_version\msbuild.exe "$directorypath\MyProject.sln" /p:Configuration=Release
# Run the tests using nUnit
cmd /c $directorypath\build\nunit\nunit-console.exe $solutionPath\MyProject.Tests\bin\debug\MyProject.Tests.dll
# Copy the license to the appropriate directory
Copy-Item -LiteralPath "$directorypath\mylicensefile.txt" "$directorypath\bin\release" -Force
# NOTE: You are going to have to adjust this to match your solution and projects.
In this post on Microsoft Connect the answer is much simpler:
Referenced assemblies in Unit Test are not copied in TestResults/Out
So what I did was the following:
[TestClass]
[DeploymentItem("Some.dll")]
public class SomeTests
{
...
}
It works fine for me.
Hope it help.

Is there a way in ANT to extract one class file from a JAR and put it in another JAR?

My ANT build script uses a WebSphere command called createEJBStubs that produces a JAR file with everything plus one new generated class, namely: com/myapp/services/_User_Service_Stub.class.
Since this stub class is only used for running JUnit tests at dev time, I would like it to be in its own JAR file.
How can I tell ANT to copy everything in AAA.JAR that matches, say, _*Stub.class and copy only those files into BBB.JAR (also, maintaining the same directory/package structure)?
Any ideas or pointers would be GREATLY appreciated! Thanks,
Rob
Ok -- answering my own question -- that was surprisingly easy. Sorry I asked.
<unzip src="AAA.JAR" dest="./temp">
<patternset>
<include name="**/_*Stub.class" />
</patternset>
</unzip>
<zip destfile="BBB.JAR" basedir="./temp" />
Thanks ANT.

Get code from TFS with nant

I want to take latest source from the Team Foundation Source control project directory to my local machine directory using NAnt build script.
for that i have used:-
<?xml version="1.0"?>
<project name="TFUse_GetFiles" default="GetTFSFiles">
<target name="GetTFSFiles" >
<exec program="C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe">
<arg value="get" />
<arg value="/login:Domain name\loginid,password" />
<arg value="$/Projects/dir/Main" />
<arg value="/force" />
</exec>
</target>
</project>
the result is showing as [exec]All files are up to date , but no files are copied to my local folder..
So please help me about this probleam if any body has done above mentioned task before.
Thanks,
The TFS client will only download files that are out of date according to the TFS server: it knows previous what gets have taken place to the workspace.
You could use the /force option on tf get to get everything whatever the server has recorded.
It's like Richard says, in addition: if your $/Projects/dir/Main is not a valid source path, TF.exe again replies with "All files are up to date".
You can find the valid path by navigating within source control explorer to the target path & then checking the 'Source location' entry.
Adding /recursive as an argument solved my problem of NAnt returning "All files are up to date" even though there were in fact new and updated files to get.

MSBuild Fails to remove Binaries directory

I am building two solutions with MSBuild:
<ItemGroup>
<SolutionToBuild Include="$(BuildProjectFolderPath)/HostASPX/SolutionA.sln"/>
<SolutionToBuild Include="$(BuildProjectFolderPath)/../Installer/SolutionB.sln"/>
</ItemGroup>
It seems that this build fails with the error message:
Unable to remove directory "c:\TeamBuild\Team Solutions\Solution\Binaries". The directory is not empty.
It appears that MSBuild creates this 'Binaries' directory by default and the build passes. When I build again the build fails with the above message. If I try a 3rd build.. it works again.
Can someone tell me how to ensure that his folder is deleted/overwritten each time?
You sure there isn't an observer effect at play? i.e., something isn't locking the directory like explorer.exe :P
You can rule it out by using \\live.sysinternals.com\procmon.exe (to find out who is doing what to the dir) and procexp (to find out who is locking it).
I experienced the same problem of "Unable to remove directory ... the directory is not empty" while running a target that looks something like this:
<Target Name="CleanFiles"
DependsOnTargets="Prepare_Files"
Inputs="#(Files->'%(OutputPath)'->Distinct())"
Outputs="_Non_Existent_Item_To_Batch_">
<ItemGroup>
<DirsToDelete Include="#(Files->'%(OutputPath)'->Distinct())"/>
</ItemGroup>
<RemoveDir Directories="#(DirsToDelete)"/>
</Target>
Occasionally it worked fine and deleted the directories, but often I got the error above.
Eventually I found out that MSBuild itself is locking the files, beacuase they appear on the target's "Inputs", and not unlocking them in time for RemoveDir to delete them.
Changing the above to:
<Target Name="CleanFiles"
DependsOnTargets="Prepare_Files">
<ItemGroup>
<DirsToDelete Include="#(Files->'%(OutputPath)'->Distinct())"/>
</ItemGroup>
<RemoveDir Directories="#(DirsToDelete)"/>
</Target>
seems to solve the problem.
It's still OK to delete all directories always since RemoveDir skips non-existent directories and does not report an error.

Resources