Using MSBuild to zip up multiple project directori

2019-04-10 01:46发布

问题:

As part of my build process in MSBuild 4.0, I end up with the following directory structure:

\OutDir
    \ProjectA
      \File1.dll  
      \File2.dll  
      \File3.exe
    \ProjectB
      \Subfolder1
        File4.html
      \File5.dll  
      \File6.dll  
      \File7.exe
    \ProjectC
      \File8.dll  
      \File9.exe

I want to be able to create one zip file per subfolder of \OutDir. If I do the following:

<ItemGroup>
  <ZipSource Include="\OutDir\**.*" />
</ItemGroup>

<MSBuild.Community.Tasks.Zip
  Files="@(ZipSource)"
  ZipFileName="OutDir\%(ZipSource.RecursiveDir)ZippedOutput.zip"
  WorkingDirectory="OutDir" />

then each subfolder is recursively zipped up, which works fine for ProjectA and ProjectC, but ProjectB ends up with two zip files, one of its root level and one of its subfolder.

My other requirement is that the number of projects is not known by the build file, so I can't just create an ItemGroup and enumerate the projects that I want zipped up.

This task would be easy in NAnt through its foreach task, but how can I achieve this in MSBuild, preferably without resorting to custom tasks?

回答1:

I came up with a workaround - a combination of the MSBuild Extension pack's FileUnder task, to enumerate the ProjectX folders that I want to zip up, and the Exec task invoking 7Zip. The code is:

<MSBuild.ExtensionPack.FileSystem.FindUnder
    TaskAction="FindDirectories"
    Path="$(WebOutputFolder)"
    Recursive="False">
    <Output ItemName="WebsiteFolders" TaskParameter="FoundItems" />
</MSBuild.ExtensionPack.FileSystem.FindUnder>

<Exec Command="7za.exe a -r %22$(OutDir)%(WebsiteFolders.Filename)-$(Configuration)-$(AssemblyFileVersion).zip%22 %22@(WebsiteFolders)\*%22" />

So now each zip file is named after the folder its contents came from (as well as configuration and versioning details), so I'll have files in my output folder named ProjectA-Debug-0.1.2.345.zip etc.



回答2:

That will most likely be because the native .Net framework zip functionality cannot do nested folders, only files - if the task you are using uses this functionality then you will be out of luck.

Also your syntax for the ZipSource Include="\OutDir\**.*" is slightly wrong, try using <ZipSource Include="\OutDir\**\*.*" instead.

If that doesn't work, try using the Zip task from the MSBuild Extension tasks, it does what you need. (Here is the doco for it).