Zipping files in a folder MSBuild - msbuild

A folder named Test_UL contains files like Test_file_UL.exe, Test_file_UL.iso and Test_file_UL.txt.
I need to zip the Test_file_UL.exe and Test_file_UL.iso files to Test.zip, excluding Test_file_UL.txt.
How can I do this using MSBuild?

You can do this by creating an ItemGroup for the items you want, and then passing that item group to a powershell cmdlet.
<ItemGroup>
<ZipFiles Include="Test_UL\Test_file_UL.exe" />
<ZipFiles Include="Test_UL\Test_file_UL.iso" />
</ItemGroup>
All the usual rules for item groups apply, so you can do whatever filtering you need.
Then invoke powershell to zip the files:
<Target Name="CreateZip">
<Exec Command="PowerShell -NoProfile -Command Compress-Archive #(ZipFiles->'%(Identity)', ',') -DestinationPath $(ZipName)" />
</Target>
Compress-Archive is a powershell cmdlet available in PowerShell
5 onwards.
#(ZipFiles->'%(Identity)', ',') is an MSBuild Transform,
changing the files into a comma separated list.
There are also MSBuild extensions that add a zip/compress target, but I've always found it easier to just quickly call powershell.

Related

Build script to copy files from various source folder to various destination folder

The basic requirement is to copy the various files and folders from different solution/project directories to the single build_output folder(/subfolders).
Currently, I am doing this operation using the Robocopy commands. The only issue is my script is too long just using multiple Robocopy commands.
<Copy SourceFiles="$(Docs)\Manual.pdf" DestinationFolder="$(BuildPath)\Help"/>
<RoboCopy Source="$(Web1)" Destination="$(BuildPath)" Files="*.aspx" Options="/E"/>
<RoboCopy Source="$(Web1)\Images" Destination="$(BuildPath)\Images" Files="*.jpg;*.png" Options="/E"/>
<RoboCopy Source="$(Web2)\Images" Destination="$(BuildPath)\Images" Files="*.jpg;*.png" Options="/E"/>
<!--- 100s of such RoboCopy & Copy commands (note that in last two commands i need to copy from different sources to same destination -->
How this job is implemented in real enterprise applications, so that
the build script is concise and clear.
Is my thinking below is the way to approach the solution. If yes, can anybody provide me sample steps using MSBuild or CommandScript easily. (free to use any MSBuild extensions)
Define the mapping of the all source folders, file types (can be xyz.png/.png/.*) and the destination path.
Copy the files (Robocopy) using the above mentioned mappings using a single target or task)
Is there any other better way to do this problem?
Insights/Solution ???
I do exactly this sort of thing to stage build output for harvesting by the installer build. I have a custom targets file for consistent processing and have some msbuild property files with the item groups describing that needs to be done.
<ItemGroup Label="AcmeComponent1Payload">
<FileToHarvest Include="$(SourceRoot)AcmeProjects\ServerManager\$(Configuration)\**\*;
$(SourceRoot)Library\SQLServerCompact\**\*;
$(SourceRoot)Utility Projects\PropertyDataValidator\PropertyDataValidator\bin\$(Configuration)\PropertyDataValidator.*"
Exclude="$(SourceRoot)Server Manager Projects\AcmeServerManager\$(Configuration)\IntegrationTests.*;
$(SourceRoot)Server Manager Projects\AcmeServerManager\$(Configuration)\**\Microsoft.Practices.*.xml;
$(SourceRoot)Server Manager Projects\AcmeServerManager\$(Configuration)\obj\**\*;
$(SourceRoot)Server Manager Projects\AcmeServerManager\$(Configuration)\**\Microsoft.VisualStudio.*;
$(SourceRoot)Server Manager Projects\AcmeServerManager\$(Configuration)\**\Microsoft.Web.*;
$(SourceRoot)Utility Projects\PropertyDataValidator\PropertyDataValidator\bin\$(Configuration)\PropertyDataValidator.xml">
<Group>AcmeServerManager</Group>
<SubDir>Utilities\</SubDir>
</FileToHarvest>
</ItemGroup>
The custom targets file has the functionality to process it.
<Target Name="CopyFiles">
<Copy Condition="#(FileToHarvest)!=''"
SourceFiles="#(FileToHarvest)"
DestinationFiles="#(FileToHarvest->'$(OutputPath)\%(Group)\%(SubDir)%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="true" />
</Target>
You can make the properties file as simple or as complicated as you like. I use multiple ones and import them into the project file using wildcards.
Thanks #daughey, I got my first part working, where I need to copy from different sources to the same destination.
<!--Declare an ItemGroup that points to source Locations-->
<ItemGroup>
<ItemToCopy Include="$(Web1)\Audit"/>
<ItemToCopy Include="$(Utilities)\Service"/>
<ItemToCopy Include="$(Web1)\NET"/>
</ItemGroup>
<!--Declare an ItemGroup that points to destination Locations-->
<ItemGroup>
<DestLocations Include="$(BuildPath)" />
</ItemGroup>
<Target Name="CopyFiles">
<!-- Run the copy command to copy the item to your dest locations-->
<!-- The % sign says to use Batching. So Copy will be run for each unique source ItemToCopy(s) in the DestLocation.-->
<RemoveDir Directories="$(BuildPath)"/>
<Message Importance="high" Text="Deploy folder is $(BuildPath)"/>
<RoboCopy Source="%(ItemToCopy.FullPath)" Destination="$(BuildPath)" Files="*.dll"/>
</Target>
After struggling with Item Metadata for Task Batching, the second part is also working great.
Scenario: Copy files from list of source directories to output directory on their respective sub-folders
$(Web1)\Audit*.dll => $(BuildPath)\Audit*.dll
$(Utilities)\Service*.jpg => $(BuildPath)\Utilities\Service*.jpg
Solution
<!--Modify an ItemGroup with metadata-->
<ItemGroup>
<ItemToCopy Include="$(Web1)\Audit">
<ToPath>$(BuildPath)\Audit</ToPath>
<FileType>*.dll</FileType>
</ItemToCopy>
<ItemToCopy Include="$(Utilities)\Service">
<ToPath>$(BuildPath)\Utilities\Service</ToPath>
<FileType>*.jpg;*.bmp</FileType>
</ItemToCopy>
</ItemGroup>
<Target Name="CopyBatch">
<RoboCopy Source="%(ItemToCopy.Identity)" Destination="%(ItemToCopy.ToPath)" Files="%(ItemToCopy.Filetype)"/>
</Target>

How to use MSBuild to xcopy only modified or new files recursively?

I need some help using MSBuild to xcopy files to two directories.
First I found out about Sayed's after.xyz.sln.targets. This will ensure that copy file tasks will run regardless of actual Build occurs or not.
I wanted to use that to copy only new or modified only files to two target directories. So I need some sort of comparison code also. Steps that I can think of.
compare dir1 to dir2 and find any new or modified files in dir1.
copy those files to dir2 recursively.
then copy the exact file sets to dir3 recursively.
TIA.
You will need to use a parameter SkipUnchangedFiles of the Copy task. Example:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MySourceFiles Include="c:\MySourceTree\**\*.*"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy
SourceFiles="#(MySourceFiles)"
DestinationFiles="#(MySourceFiles->'c:\MyDestinationTree\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="true"
/>
</Target>
</Project>

USe MSBuild properties in windows batch command line?

defined some msbuild properties, is it possible to 'promote' it to be used in the windows batch file? i.e. in my .bat file write something 'echo %CustomProperty%' where the CustomProperty is defined in the msbuild script
Accessing MSbuild properties within a batch file doesn't seem to be the correct release approach and does not seem necessary. The same facility is easily available within Msbuild itself. In your example case you can use something like the following:
<Message Text="Copying $(ZipFile) to $(PublicFolderToDropZip)" Importance="high" />
to achieve what you were looking.
You can even run batch files in the following manner:
<Target Name="Default">
<Exec Command="CALL mybatch.cmd" />
</Target>

Listing contents of a directory using msbuild

I'm trying to debug an msbuild script that is being run on our TFS build agent. I have no permissions to the build agent server.
Is there a way I can add some debugging to my msbuild script ("Message" or similar) to output a listing of all the files in a given directory?
Hope this helps to list all the files in the folder where the MSBuild files are there recursively:
<Target Name="Listing">
<ItemGroup>
<PackageFiles Include="$(MSBuildProjectDirectory)\**\*.*;"/>
</ItemGroup>
<Message Text="%(PackageFiles.FullPath)"/>
</Target>

MSbuild command line parameter for skipping the directory

I have following command line parameters in team city for deployment. everything works fine but i want to skip some directory while deployment. how can i add that logic in following msbuild script in team city
/P:Configuration=%env.Configuration%
/P:DeployOnBuild=True
/P:DeployTarget=MSDeployPublish
/P:MsDeployServiceUrl=https://%env.TargetServer%/MsDeploy.axd
/P:AllowUntrustedCertificate=True
/P:MSDeployPublishMethod=WMSvc
/P:CreatePackageOnPublish=True
/P:SkipExtraFilesOnServer=True
/P:UserName=xxxxx
/P:Password=xxxxx
I was working on the same thing. I didn't like having to modify my .csproj file, so I tried this. It is working for me so far. In my case, I was excluding the media, App_Data\Logs, and App_Data\preview folders from deployment instead of the Data folder.
Basically, you can pass the ExcludeFoldersFromDeployment as a parameter to MSBuild. Combining that with the SkipExtraFilesOnServer does the trick.
/p:Configuration=Debug
/p:DeployOnBuild=True
/p:DeployTarget=MSDeployPublish
/p:MsDeployServiceUrl=OurDevWebServer/msdeployagentservice
/p:AllowUntrustedCertificate=True
/p:MSDeployPublishMethod=RemoteAgent
/p:CreatePackageOnPublish=True
/p:DeployIisAppPath=umbraco_TestSite
/p:IgnoreDeployManagedRuntimeVersion=True
/p:SkipExtraFilesOnServer=True
/p:ExcludeFoldersFromDeployment="media;App_Data\Logs;App_Data\preview"
/p:IncludeSetAclProviderOnDestination=False
/p:AuthType=NTML /p:UserName=
You can't specify a WPP skip rule via the command line because they are declared as items, not properties.
Here is the syntax for declaring the skip rule inside your pubxml (or wpp.targets):
<ItemGroup>
<MsDeploySkipRules Include="SkipErrorLogFolder1">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>ErrorLog</AbsolutePath>
</MsDeploySkipRules>
</ItemGroup>
Actually I already implement this in my project as follow:
<ItemGroup>
<MsDeploySkipRules Include="SkipDeleteApp_Data_Import">
<SkipAction></SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>$(_Escaped_WPPAllFilesInSingleFolder)\\App_Data\\Import</AbsolutePath>
</MsDeploySkipRules>
</ItemGroup>
<ItemGroup>
<MsDeploySkipRules Include="SkipDeleteApp_Data_File">
<SkipAction></SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>$(_Escaped_WPPAllFilesInSingleFolder)\\App_Data\\en-US-custom.txt</AbsolutePath>
</MsDeploySkipRules>
</ItemGroup>