nishantcop
nishantcop

Reputation: 1017

Zip files after build completes in Visual Studio

I have a requirement where I need to zip some files after I build a solution file.

Could this be achieved automatically once I build my project in Release/Debug mode?

Upvotes: 26

Views: 43575

Answers (7)

Vishal Chikhalikar
Vishal Chikhalikar

Reputation: 11

  1. Right Click on Project=> Select Properties
  2. Click on BuildEvent
  3. Add the below Code in the post-Build event command Line without double quote
if exist $(AssemblyName).zip (  Del $(AssemblyName).zip)
powershell.exe -command Compress-Archive -Path $(AssemblyName).dll, *dll -DestinationPath $(AssemblyName).zip
  1. It will Generate the zip file of all .dll in the "bin/release" folder

Upvotes: 1

ursa
ursa

Reputation: 4611

Cross-platform zip for .Net Core projects:

<Project Sdk="Microsoft.NET.Sdk">
    ...
    <ItemGroup>
        <SourcesFiles Include="src/**/*.cs">
            <InProject>false</InProject>
        </SourcesFiles>
        <SourcesFiles Include="../shared/src/**/*.cs">
            <InProject>false</InProject>
            <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
            <CopyToOutputDirectory>Never</CopyToOutputDirectory>
        </SourcesFiles>
    </ItemGroup>
    <Target Name="ZipSources">
        <Zip Files="@(SourcesFiles)" OutputFilename="$(SourcesZipFile)"/>
    </Target>
    <UsingTask
        TaskName="Zip"
        TaskFactory="RoslynCodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)/Microsoft.Build.Tasks.Core.dll" >
        <ParameterGroup>
            <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
            <OutputFilename ParameterType="System.String" Required="true" />
        </ParameterGroup>
        <Task>
            <Using Namespace="System"/>
            <Using Namespace="System.IO"/>
            <Using Namespace="System.IO.Compression" />
            <Using Namespace="System.Linq" />
            <Code Type="Fragment" Language="cs"><![CDATA[
Log.LogMessage("Creating ZIP archive [OutputFilename: " + OutputFilename + ", Files: [\n\t" +
    Files.Select(it => it.GetMetadata("FullPath")).Aggregate((a, b) => a + ",\n\t" + b) + "\n]]");

string zipFile = Path.GetFullPath(OutputFilename);
Directory.CreateDirectory(Path.GetDirectoryName(zipFile));

using (Stream zipStream = new FileStream(zipFile, FileMode.Create, FileAccess.Write))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create))
{
    foreach (ITaskItem fileItem in Files) {
        string filename = fileItem.ItemSpec;
        string entryName = fileItem.GetMetadata("Link");
        if (entryName == string.Empty)
            entryName = fileItem.GetMetadata("RecursiveDir") + fileItem.GetMetadata("Filename") + fileItem.GetMetadata("Extension");
        //Log.LogMessage("entryName: " + entryName + ", filename: " + filename);

        using (Stream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
        using (Stream fileStreamInZip = archive.CreateEntry(entryName).Open())
            fileStream.CopyTo(fileStreamInZip);
    }
}
            ]]></Code>
        </Task>
    </UsingTask>

Upvotes: 0

Martin Lisowski
Martin Lisowski

Reputation: 697

I could not get Build Events to work so I modified the MS Build configuration file - the *.csproj file. It's actually not black magic and documented by MS here: https://learn.microsoft.com/en-us/visualstudio/msbuild/build-process-overview?view=vs-2022

You have to Unload your project in VS, modify the *.csproj file (VS will load it automatically when you unload the project) and then Reload the project from Solution Explorer.

Here is a snipped from the Build target (in this case it only zips the application files):

<Target Name="Build">
  <CreateItem Include="app\**">
    <Output ItemName="ApplicationFiles" TaskParameter="Include" />
  </CreateItem>
  <Zip ZipFileName="out\$(AssemblyName).zip" WorkingDirectory="$(MSBuildProjectDirectory)\app" Files="@(ApplicationFiles)" />
</Target>

This Zip 'task' of MS Build seems to be much faster than the PowerShell Compress function.

Here is a list of available MS Build 'tasks':

https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-task-reference?view=vs-2022

There is also an MS Build task that will zip an entire directory including subdirectories, like so:

<ZipDirectory SourceDirectory="dist" DestinationFile="out\$(AssemblyName).zip" />

Upvotes: 1

gpkarnik
gpkarnik

Reputation: 49

This worked for me:

if $(ConfigurationName) == Debug (powershell -Command "Get-ChildItem -Path '$(TargetDir)publish' -Recurse|Compress-Archive -DestinationPath '$(SolutionDir)PublishOutput\$(ProjectName)-$(ConfigurationName).zip' -Force")

Upvotes: 2

ArieKanarie
ArieKanarie

Reputation: 1023

Using powershell, only when doing Release build:
if $(ConfigurationName) == Release (powershell Compress-Archive -Path '$(TargetDir)*.dll', '$(TargetDir)*.pdb', '$(TargetDir)*.config' -DestinationPath '$(SolutionDir)PublishOutput\YourNameHere.zip' -Force)

It only zips the dll, pdb and config files.
-Force is used to overwrite the zip file on each build.

Upvotes: 30

TaW
TaW

Reputation: 54453

Go to the properties of your project and in the 'Build Events' tab write your commands in the Post-Build event area. The commands there execute just like (or as) a Cmd batch file.

Also: there ara a few 'makros' available there, which may help referring to the project folders etc.. Check it out.

And, to add to Jason's comment, you can also call the batch file itself as the post-build command.

(One caveat about post-build events: They are executed after the build. But if you have CSC targets they are compiled after the build and after the post-build events. If you want to e.g.copy the output files of these CSC targets you need to do it in a post-compile event.)

Upvotes: 4

Christian Specht
Christian Specht

Reputation: 36451

Usually I don't put stuff like creating zip files, installers, NuGet packages etc. into my actual project.
Why? Because when I put it there, it gets executed each time I'm building the project in Visual Studio, for example when I'm debugging.
But zip files, installers etc. are only needed when I do a release, so I don't want to wait for them to be re-generated each time I press F5 in Visual Studio.

To make a release, I usually create a batch file that executes a MSBuild project file, which creates everything that's necessary to make a release.
IMO creating a ZIP file belongs into that MSBuild project file as well.

You can find all the information you need in these two previous answers by me:

Plus, here's an example MSBuild project file from one of my projects, which does the following:

  • build the project
  • run unit tests
  • create two release folders with binaries (one DLL and one .exe)
  • create two zip files, one for each of the folders with binaries
  • create a NuGet package for the DLL
  • create a ClickOnce setup for the .exe
  • automatically set the correct version number for everything

The great thing about this approach is that I can make a release, which includes everything I have just listed, with a single click (running a batch file).
Creating all this stuff takes some time, but as it's not part of the Visual Studio solution, it doesn't run each time I do a build in Visual Studio - I only execute it when I really need it.

Upvotes: 11

Related Questions