Copy the content of the bin folder into a specific folder - msbuild

So far I have this,but it's not working.
<Target Name="AfterBuild">
<Copy SourceFiles="bin\" DestinationFolder="C:\temp\appServer\"></Copy>
</Target>

Try this :
<ItemGroup>
<BinFiles Include="bin\**\*.*"/>
</ItemGroup>
<Target Name="AfterBuild">
<Copy SourceFiles="#(BinFiles)"
DestinationFolder="C:\temp\appServer\"/>
</Target>

Looks like the MSBuild Copy task doesn't take a directory for SourceFiles, but instead a list of files to copy.
Check out the MSDN article here for a simple example:
MSDN Link

Try using a file wildcard.
<Target Name="AfterBuild">
<Copy SourceFiles="bin\*.*" DestinationFolder="C:\temp\appServer\"></Copy>
</Target>

Related

Deleting parent folder msbuild

Am passing the the below path as parameter to msbuild project.
"D:\Tools\TestTools\Folder1\Folder2\Folder3"
How to I delete the "Folder1" by traversing this parameter using msbuild?
Thanks...
You could just split the path twice:
<Target Name="DeleteSubDir" DependsOnTargets="">
<PropertyGroup>
<Dir>D:\Tools\TestTools\Folder1\Folder2\Folder3</Dir>
<DirToDelete>$([System.IO.Path]::GetDirectoryName('$(Dir)'))</DirToDelete>
<DirToDelete>$([System.IO.Path]::GetDirectoryName('$(DirToDelete)'))</DirToDelete>
</PropertyGroup>
<RemoveDir Directories="$(DirToDelete)" />
</Target>
Just explicitly go two directories above:
<Target Name="DeleteSubDir" DependsOnTargets="">
<PropertyGroup>
<Dir>D:\Tools\TestTools\Folder1\Folder2\Folder3</Dir>
<DirToDelete>$([System.IO.Path]::GetFullPath('$(Dir)\..\..'))</DirToDelete>
</PropertyGroup>
<RemoveDir Directories="$(DirToDelete)" />
</Target>

Deleting files on a remote machine (shared folder) using msbuild

I want to delete files kept in a shared folder on a remote machine using msbuild. I have googled but couldn't get a proper solution. Please help.
Thank you
To answer my own question: Following code is working.
<ItemGroup>
<ServiceLocation Include="\\ServerName\FolderName\*.*"></ServiceLocation>
</ItemGroup>
<Target Name="Deploy">
<Delete Files="#(ServiceLocation)" />
</Target>
try with this one,
<Target Name="SomeTarget">
<ItemGroup>
<FilesToDelete Include="Path\To\Obj\**\*"/>
</ItemGroup>
<Delete Files="#(FilesToDelete)" />
</Target>

In MSBuild, can I use the String.Replace function on a MetaData item?

In MSBuild v4 one can use functions (like string.replace) on Properties. But how can I use functions on Metadata?
I'd like to use the string.replace function as below:
<Target Name="Build">
<Message Text="#(Files->'%(Filename).Replace(".config","")')" />
</Target>
Unfortunately this outputs as (not quite what I was going for):
log4net.Replace(".config","");ajaxPro.Replace(".config","");appSettings.Replace(".config","");cachingConfiguration20.Replace(".config","");cmsSiteConfiguration.Replace(".config","");dataProductsGraphConfiguration.Replace(".config","");ajaxPro.Replace(".config","");appSettings.Replace(".config","");cachingConfiguration20.Replace(".config","");cmsSiteConfiguration
Any thoughts?
You can do this with a little bit of trickery:
$([System.String]::Copy('%(Filename)').Replace('config',''))
Basically, we call the static method 'Copy' to create a new string (for some reason it doesn't like it if you just try $('%(Filename)'.Replace('.config',''))), then call the replace function on the string.
The full text should look like this:
<Target Name="Build">
<Message Text="#(Files->'$([System.String]::Copy("%(Filename)").Replace(".config",""))')" />
</Target>
Edit: MSBuild 12.0 seems to have broken the above method. As an alternative, we can add a new metadata entry to all existing Files items. We perform the replace while defining the metadata item, then we can access the modified value like any other metadata item.
e.g.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Files Include="Alice.jpg"/>
<Files Include="Bob.not-config.gif"/>
<Files Include="Charlie.config.txt"/>
</ItemGroup>
<Target Name="Build">
<ItemGroup>
<!--
Modify all existing 'Files' items so that they contain an entry where we have done our replace.
Note: This needs to be done WITHIN the '<Target>' (it's a requirment for modifying existing items like this
-->
<Files>
<FilenameWithoutConfig>$([System.String]::Copy('%(Filename)').Replace('.config', ''))</FilenameWithoutConfig>
</Files>
</ItemGroup>
<Message Text="#(Files->'%(FilenameWithoutConfig)')" Importance="high" />
</Target>
</Project>
Result:
D:\temp>"c:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" /nologo test.xml
Build started 2015/02/11 11:19:10 AM.
Project "D:\temp\test.xml" on node 1 (default targets).
Build:
Alice;Bob.not-config;Charlie
Done Building Project "D:\temp\test.xml" (default targets).
I needed to do something similar, the following worked for me.
<Target Name="Build">
<Message Text="#(Files->'%(Filename)'->Replace('.config', ''))" />
</Target>
Those functions works in properties only (as I know). So create target which will perform operation throw batching:
<Target Name="Build"
DependsOnTargets="ProcessFile" />
<Target Name="ProcessFile"
Outputs="%(Files.Identity)">
<PropertyGroup>
<OriginalFileName>%(Files.Filename)</OriginalFileName>
<ModifiedFileName>$(OriginalFileName.Replace(".config",""))</ModifiedFileName>
</PropertyGroup>
<Message Text="$(ModifiedFileName)" Importance="High"/>
</Target>
Do you really need in your example such kind of task? I mean there exists MSBuild Well-known Item Metadata
EDIT: I should specify that this task processes all items in #(Files).
i dont think you can use functions directly with itemgroups and metadata (that would be easy)
However you can use batching:
Taking the ideas from this post:
array-iteration
I was trying to trim an itemgroup to send to a commandline tool (i needed to lose .server off the filename)
<Target Name="ProcessFile" DependsOnTargets="FullPaths">
<ItemGroup>
<Environments Include="$(TemplateFolder)\$(Branch)\*.server.xml"/>
</ItemGroup>
<MSBuild Projects=".\Configure.msbuild"
Properties="CurrentXmlFile=%(Environments.Filename)"
Targets="Configure"/>
</Target>
<Target Name="Configure" DependsOnTargets="FullPaths">
<PropertyGroup>
<Trimmed>$(CurrentXmlFile.Replace('.server',''))</Trimmed>
</PropertyGroup>
<Message Text="Trimmed: $(Trimmed)"/>
<Exec Command="ConfigCmd $(Trimmed)"/>
</Target>
For MSBuild 12.0, here's an alternative.
<Target Name="Build">
<Message Text="$([System.String]::Copy("%(Files.Filename)").Replace(".config",""))" />
</Target>
Got the same problem (except with MakeRelative), so I passed with another solution : Using good old CreateItem that take a string and transform to Item :)
<ItemGroup>
<_ToUploadFTP Include="$(PublishDir)**\*.*"></_ToUploadFTP>
</ItemGroup>
<CreateItem Include="$([MSBuild]::MakeRelative('c:\$(PublishDir)','c:\%(relativedir)%(filename)%(_ToUploadFTP.extension)'))">
<Output ItemName="_ToUploadFTPRelative" TaskParameter="Include"/>
</CreateItem>
<FtpUpload Username="$(UserName)"
Password="$(UserPassword)"
RemoteUri="$(FtpHost)"
LocalFiles="#(_ToUploadFTP)"
RemoteFiles="#(_ToUploadFTPRelative->'$(FtpSitePath)/%(relativedir)%(filename)%(extension)')"
UsePassive="$(FtpPassiveMode)" ></FtpUpload>

Msbuild compile website without placing the site in IIS

I am trying to create a msbuild script that will compile and place a test app into a folder on my desktop. I do not want this app published to IIS. I have followed several blgos and looked through hashimi's book but I still cannot figure this out. Below is my script. Thank you very much!
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Clean">
<ItemGroup>
<BinFiles Include="bin\*.*" />
</ItemGroup>
<Delete Files="#(BinFiles)" />
</Target>
<Target Name="Compile" DependsOnTargets="Clean">
<MSBuild Projects="test.vbproj"/>
</Target>
<Target Name="Publish" DependsOnTargets="Compile">
<RemoveDir Directories="$(OutputFolder)"
ContinueOnError="true"/>
<MSBuild Projects="test.vbproj"
targets="ResolveReferences;_CopyWebApplication"
Properties="WebProjectOutputdir=$(OutputFolder; OutDir=$WebProjectOutputDir)\"/>
</Target>
</Target>
</Project>
Your script is a bit awkward (you redefined the clean target to do the same as the the basic clean target).
I'm pretty sure your problem comes from the CopyWebApplication which does lots of stuff according to the properties set in your project file and pass by command line.
Can you try the following script :
<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Compile">
<MSBuild
Projects="test.vbproj"
Targets="Clean;Build"
Properties="OutputPath=C:\tmp"/>
</Target>
</Project>
if your test project is a website then the build target should create it on the folder specified in the OutputPath/OutDir property

How to create copying items from property values?

Let's say I have a list of sub paths such as
<PropertyGroup>
<subPaths>$(path1)\**\*; $(path2)\**\*; $(path3)\file3.txt; </subPaths>
</PropertyGroup>
I want to copy these files from folder A to folder B (surely we already have all the sub folders/files in A). What I try was:
<Target Name="Replace" DependsOnTargets="Replace_Init; Replace_Copy1Path">
</Target>
<Target Name="Replace_Init">
<PropertyGroup>
<subPaths>$(path1)\**\*; $(path2)\**\*; $(path3)\file3.txt; </subPaths>
</PropertyGroup>
<ItemGroup>
<subPathItems Include="$(subPathFiles.Split(';'))" />
</ItemGroup>
</Target>
<Target Name="Replace_Copy1Path" Outputs="%(subPathItems.Identity)">
<PropertyGroup>
<src>$(folderA)\%(subPathItems.Identity)</src>
<dest>$(folderB)\%(subPathItems.Identity)</dest>
</PropertyGroup>
<Copy SourceFiles="$(src)" DestinationFiles="$(dest)" />
</Target>
But the Copy task didn't work. It doesn't translate the **\* to files. What did I do wrong? Please help!
I don't think you can do something like that.
$(subPathFiles.Split(';')) returns a property where value are separated by semicolon, so this call is useless.
If you want to keep this mechanism you should use the task StringToItemCol from MSBuild Extension Pack :
<Target Name="Replace_Init">
<PropertyGroup>
<subPaths>$(path1)\**\*; $(path2)\**\*; $(path3)\file3.txt; </subPaths>
</PropertyGroup>
<MsBuildHelper TaskAction="StringToItemCol"
ItemString="$(subPaths)" Separator=";">
<Output TaskParameter="OutputItems" ItemName="subPathItems "/>
</MsBuildHelper>
</Target>
Otherwise, you could directly pass items with folderA and subPaths embedded :
<ItemGroup>
<subPathIt Include="$(folderA)\$(path1)\**\*"/>
<subPathIt Include="$(folderA)\$(path2)\**\*"/>
<subPathIt Include="$(folderA)\$(path3)\file3.txt" Condition="Exists('$(path3)\file3.txt')"/>
</ItemGroup>
<Target Name="Replace_Copy1Path">
<Copy SourceFiles="#(subPathItems )"
DestinationFiles="$(folderB)\%(RecursiveDir)\%(Filename)%(Extension)" />
</Target>