- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Monday, 13 May 2013

How to compress a Visual Studio Extension (VSIX) during build

Lately I’ve been working with Mads Kristensen on a cool new Visual Studio Extension, Farticus, and wanted to share with you guys one of the things that I learned.

When you are developing Visual Studio extension on of the things you should keep in mind is the download size of the extension. This is the size of the .vsix file which you upload to the gallery. If the download size is too large typically people may get impatient and cancel the install. Because of this it’s a good idea to try and get your .vsix to the smallest size possible.

The good news here is that the .vsix file is already compressed. It’s actually a .zip file renamed to .vsix. If you want to see what’s in a .vsix just rename it to .zip and extract it out. The bad news is that the CreateZipPackage task used by the Microsoft.VsSdk.targets file does not perform the best compression. Fortunately there are tasks to create Zip files that we can use. I have chosen to use the Zip task from the MSBuild Extension Pack.

Before I go over all the details let’s take a look at what the final result will be after we compress with the MSBuild Extension Pack. See the table below for the comparison for two different projects.

Project

VSIX Size Before

VSIX Size After

Reduction

Farticus 442 kb 248 kb 43 %
VS Web Essentials 2102 kb 740 kb 65 %

From the table above we can see that we can gain a significant amount of additional compression by using the MSBuild extension pack.

Below is the content that I pated into the .csproj file. I’ll paste it in it’s entirety and then explain.

<PropertyGroup>
  <EnableCompressVsix Condition=" '$(EnableCompressVsix)'=='' ">true</EnableCompressVsix>
  <BuildLib Condition=" '$(BuildLib)'=='' ">$(MSBuildProjectDirectory)\..\Build\Lib\</BuildLib>

</PropertyGroup>
<UsingTask AssemblyFile="$(BuildLib)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.Zip"/>

<Target Name="CompressVsix" 
        AfterTargets="CreateVsixContainer" 
        DependsOnTargets="PrepareReplceVsixTemp" 
        Condition=" '$(EnableCompressVsix)'=='true' ">
    
  <!-- copy the file to the obj folder and then party on it -->
  <MakeDir Directories="$(_TmpVsixDir);$(_TmpVsixDir)\Extracted\"/>

  <Copy SourceFiles="$(TargetVsixContainer)"
        DestinationFolder="$(_TmpVsixDir)">
    <Output TaskParameter="CopiedFiles" ItemName="_TmpVsixCopy"/>
  </Copy>
    
  <!-- extract out the .zip file -->
  <MSBuild.ExtensionPack.Compression.Zip 
    TaskAction="Extract" 
    ExtractPath="$(_TmpVsixDir)Extracted\" 
    ZipFileName="@(_TmpVsixCopy->'%(FullPath)')"/>

  <ItemGroup>
    <_FilesToZip Remove="@(_FilesToZip)"/>
    <_FilesToZip Include="$(_TmpVsixDir)Extracted\**\*"/>
  </ItemGroup>

  <MSBuild.ExtensionPack.Compression.Zip
    TaskAction="Create"
    CompressFiles="@(_FilesToZip)"
    ZipFileName="%(_TmpVsixCopy.FullPath)"
    RemoveRoot="$(_TmpVsixDir)Extracted\"
    CompressionLevel="BestCompression" />

  <Delete Files ="$(TargetVsixContainer)"/>
  <Copy SourceFiles="%(_TmpVsixCopy.FullPath)" DestinationFiles="$(TargetVsixContainer)" />
</Target>

<Target Name="PrepareReplceVsixTemp" DependsOnTargets="CreateVsixContainer">
  <ItemGroup>
    <_VsixItem Remove="@(_VsixItem)"/>
    <_VsixItem Include="$(TargetVsixContainer)" />

    <_TmpVsixPathItem Include="$(IntermediateOutputPath)VsixTemp\%(_VsixItem.Filename)%(_VsixItem.Extension)"/>
  </ItemGroup>
    
  <PropertyGroup>
    <_TmpVsixDir>%(_TmpVsixPathItem.RootDir)%(_TmpVsixPathItem.Directory)</_TmpVsixDir>
  </PropertyGroup>

  <RemoveDir Directories="$(_TmpVsixDir)"/>  
</Target>  

 

The snippet above perform the following actions.

  1. Remove the old VsixTemp folder from any previous build if it exists
  2. Copy the source .vsix to the intermediate output path (i.e. obj\debug or obj\release)
  3. Extract out the contents to a folder
  4. Re-zip the file using MSBuild extension pack
  5. Replace the output .vsix with the compressed one

 

When building now the .vsix in the output folder should be smaller than it was before.

In my case I have copied the necessary assemblies from the MSBuild Extension pack and placed them in the projects repository. For the Zip task you’ll need the following files.

In my case I’ve placed them in a folder named Build\lib\.

You should be able to copy/paste what I have here into your VSIX projects. You’ll need to update the path to the MSBuild extension pack assemblies if you put them in a different location. Note: I’ve only tested this with Visual Studio 2012.

The MSBuild elements used here is pretty straight forward. If you have any questions on this let me know.

 

You can find the source for the Farticus project at https://github.com/ligershark/Farticus/. Please send us a Pull (my finger) Request.

 

Thanks,
Sayed Ibrahim Hashimi | http://msbuildbook.com | @SayedIHashimi

Visual Studio 11 | vs-extension | VSIX Monday, 13 May 2013 01:11:54 (GMT Daylight Time, UTC+01:00)  #     | 
Thursday, 09 May 2013

Book published and now in stock!

I’m happy to say that my Supplement to Inside the Microsoft Build Engine book (co-author William Bartholomew) has now been published. In fact it’s already in stock and ready to be shipped by Amazon.com.

This book is a small addition (118 pages) to the previous book, Inside the Microsoft Build Engine 2nd edition. It has a small price too, MSRP is $12.99 but it’s selling on Amazon.com for $8.99! In this book we cover the updates to MSBuild, Team Build and Web Publishing in Visual Studio 2012. The foreword was written by Scott Hanselman, and you can read the entire foreword online.

Check out how thin the supplement is in comparison to the 2nd edition #ThinIsIn.

945231_10103483509401051_968543011_n

 

If you already own the 2nd edition then you’ll love this update.

 

Table of Contents

Chapter 1: What's new in MSBuild

  1. Visual Studio project compatibility between 2010 and 2012
  2. Out of Process Tasks
  3. NuGet
  4. XML Updates with SlowCheetah
  5. Cookbook
Chapter 2: What's new in Team Build 2012
  1. Installation
  2. Team Foundation Service
  3. User interface (UI) enhancements
  4. Visual Studio Test Runner
  5. Pausing build definitions
  6. Batching
  7. Logging
  8. Windows Workflow Foundation 4.5
  9. Cookbook
Chapter 3: What's new in Web Publishing
  1. Overview of the new Publish Web Dialog
  2. Building web packages
  3. Publish profiles
  4. Database publishing support
  5. Profile-specific web.config transforms
  6. Cookbook

 

The book has been available in e-book form for a few weeks. Just long enough for us to get our first review. It was 5 stars :).

image

 

Please let us know what you think of this book!

 

You can download all the samples and learn more at msbuildbook.com.

 

Sayed Ibrahim Hashimi | http://msbuildbook.com | @SayedIHashimi

msbuild | MSDeploy | Team Build | web | Web Publishing Pipeline Thursday, 09 May 2013 06:33:20 (GMT Daylight Time, UTC+01:00)  #     |