7

Here is my build script:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
  <PropertyGroup>
    <!-- Path where the solution file is located (.sln) -->
    <ProjectPath>W:\Demo</ProjectPath>
    <!-- Location of compiled files -->
    <DebugPath>W:\Demo\bin\Debug</DebugPath>
    <ReleasePath>W:\Demo\bin\Release</ReleasePath>
    <!-- Name of the solution to be compiled without the .sln extension -->         <ProjectSolutionName>DemoTool</ProjectSolutionName>

    <!-- Path where the nightly zip file will be copyd -->
    <NightlyBuildPath>W:\Nightly_Builds\Demo</NightlyBuildPath>
    <!-- Name of the nighly zip file (YYYYMMDD_NightlyZipName.zip, date added automatically) -->
    <NightlyZipName>Demo</NightlyZipName>
  </PropertyGroup>

  <ItemGroup>
    <!-- All files and folders from ./bin/Debug or ./bin/Release what will be added to the nightly zip -->
    <DebugApplicationFiles Include="$(DebugPath)\**\*.*" Exclude="$(DebugPath)\*vshost.exe*" />
    <ReleaseApplicationFiles Include="$(ReleasePath)\**\*.*" Exclude="$(ReleasePath)\*vshost.exe*" />
  </ItemGroup>

  <Target Name="DebugBuild">
    <Message Text="Building $(ProjectSolutionName) Debug Build" />
    <MSBuild Projects="$(ProjectPath)\$(ProjectSolutionName).sln" Targets="Clean" Properties="Configuration=Debug"/>
    <MSBuild Projects="$(ProjectPath)\$(ProjectSolutionName).sln" Targets="Build" Properties="Configuration=Debug"/>
    <Message Text="$(ProjectSolutionName) Debug Build Complete!" />
    <CallTarget Targets="CreateNightlyZip" />
  </Target>

  <Target Name="CreateNightlyZip">
    <PropertyGroup>
      <StringDate>$([System.DateTime]::Now.ToString('yyyyMMdd'))</StringDate>
    </PropertyGroup>
    <MakeDir Directories="$(NightlyBuildPath)"/>
    <Zip Files="@(DebugApplicationFiles)"
          WorkingDirectory="$(DebugPath)"
          ZipFileName="$(NightlyBuildPath)\$(StringDate)_$(NightlyZipName).zip"
          ZipLevel="9" />
  </Target>
</Project>

My script works perfectly, only there is one strange problem. When i build a project first time and there is no \bin\Debug folder and its created during the build, but the ZIP file still comes empty. Running the build script second time when the \bin\Debug folder is now in place with builded files then the file are added to the ZIP.

What could be the problem that running script first time the ZIP file is empty?

Castrohenge
  • 8,525
  • 5
  • 39
  • 66
hs2d
  • 6,027
  • 24
  • 64
  • 103

3 Answers3

14

The problem is in the DebugApplicationFiles item collection. It is created before the build is invoked. Move the DebugApplicationFiles into CreateNightlyZip target. Update your script this way:

<Target Name="CreateNightlyZip">
    <PropertyGroup>
      <StringDate>$([System.DateTime]::Now.ToString('yyyyMMdd'))</StringDate>
    </PropertyGroup>
    <ItemGroup>
        <DebugApplicationFiles Include="$(DebugPath)\**\*.*" Exclude="$(DebugPath)\*vshost.exe*" />
    </ItemGroup>
    <MakeDir Directories="$(NightlyBuildPath)"/>
    <Zip Files="@(DebugApplicationFiles)"
      WorkingDirectory="$(DebugPath)"
      ZipFileName="$(NightlyBuildPath)\$(StringDate)_$(NightlyZipName).zip"
      ZipLevel="9" />
</Target>
sampathsris
  • 21,564
  • 12
  • 71
  • 98
Ludwo
  • 6,043
  • 4
  • 32
  • 48
  • 1
    I checked VS 2019. There is no Zip task. Was it dropped? – videoguy Dec 20 '22 at 19:29
  • @videoguy I think the `Zip` task was only ever in the [MSBuild Extension Pack](https://github.com/mikefourie-zz/MSBuildExtensionPack). – Hugh W Jun 06 '23 at 10:17
6

If powershell 5.0 or greater is available, you could use powershell command directly.

<Target Name="Zip" BeforeTargets="AfterBuild">
  <ItemGroup>
    <ZipFiles Include="$(OutDir)release\file1.exe" />
    <ZipFiles Include="$(OutDir)release\file2.exe" />
  </ItemGroup>
  <Exec Command="PowerShell -command Compress-Archive @(ZipFiles, ',') $(OutDir)release\zippedfiles.zip" />
</Target>
Ernie S
  • 13,902
  • 4
  • 52
  • 79
ksp
  • 132
  • 1
  • 5
  • This even works with subdirectories. They are compressed using the original directory structure. – kiewic Jun 26 '16 at 16:21
  • 1
    @kiewic How did you manage to do this? In my case, since MSBuild expands the item group, a list of comma-separated paths is provided to the command line, and Compress-Archive will try to put every path provided to the root. So I get a flattened archive. I want to use the item group (instead of providing a pattern directly to Compress-Archive) because I have a lot of excludes etc. – realMarkusSchmidt Sep 23 '16 at 08:34
  • @realMarkusSchmidt were you able to zip keeping the original structure? I'd like to achieve the same. – kerzek Jun 05 '17 at 17:04
  • @kerzek, sorry, no. I used a native code task and System.IO.Compression instead. Here is some sample code that might give you an impression (you can also save that to a dedicated file and include it from your actual build scripts): https://peteris.rocks/blog/creating-release-zip-archive-with-msbuild/ – realMarkusSchmidt Jun 06 '17 at 06:29
  • @realMarkusSchmidt great, I'll use the System.IO.Compression method, thanks Markus. – kerzek Jun 07 '17 at 12:15
2

Should you wish to zip a whole folder for 'xcopy deploy', since MSBuild 15.8 there is a simple way - the ZipDirectory build task.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <Target Name="ZipOutputPath" AfterTargets="Build">
        <ZipDirectory
            SourceDirectory="$(OutputPath)"
            DestinationFile="$(OutputPath)\..\$(AssemblyName).zip"
            Overwrite=="true" />
    </Target>

</Project>

[1] https://learn.microsoft.com/en-us/visualstudio/msbuild/zipdirectory-task?view=vs-2019

Tim Lovell-Smith
  • 15,310
  • 14
  • 76
  • 93
  • not powerful enough, cannot exclude files. And set `AfterTargets="Build"` will compress the full release directory when publishing, that's suck. – Mr. Squirrel.Downy Mar 22 '23 at 02:38