Click here to Skip to main content
13,446,453 members (37,877 online)
Click here to Skip to main content
Add your own
alternative version


49 bookmarked
Posted 8 Jul 2009

Zip My Code

, 20 Dec 2009
Rate this:
Please Sign up or sign in to vote.
A utility stripping your source code to the essential core and then compressing it to a nice CodeProject article attachment.



This article will present you with a utility that may come in handy if you are a contributor on CodeProject. The utility eases stripping down the source to the pure essential of what article code attachments should be. It is also very handy to do so, using simple drag-and-drop or the console interface. If enough people find it useful, it may earn its place as an author tool on the Free Tools for Authors page, which according to me is rather scant.

I am aware that this article won't get any good ratings or popularity, it is after all a very basic application. It focuses on solving a minor problem rather than presenting you with really cool code. There are, however, some grains of gold buried within the application that might interest some of you.


  • First and foremost credit goes to CodeProject member SAKryukov for taking his time to review the article and give extremely constructive feedback.
  • MADEBITS for their NETZ, a utility I use for compressing and packing ZipMyCode into one assembly.
  • The ICSharpCode team for their SharpZipLib, an assembly I use for Zip compression.
  • CodeProject member Peter Palotas for his Plossum command line parser.

How to Use the Utility

The UI Part

  1. Type or press the Browse... button and select the source path.
  2. Press Start zipping my code.
  3. A compressed zip archive will be created alongside your source.

You have the option to add, edit, and remove exclude patterns by expanding Options.

The Console Part

The application has, in addition to the UI, a command line interface:

C:\>ZipMyCode /?
ZipMyCode  version
Copyright © 2009

   ZipMyCode path [/c:file] [/e:value[+value]] [/o:file]
   ZipMyCode /u

Strip and compress:
   /c,                 Specifies the configuration file with exclude
   /configuration      patterns, one pattern per line. If file is
                       specified, the default exclude patterns are ignored.
   /e, /exclude        Specifies the list of exclude patterns. If patterns are
                       specified, the default exclude patterns are ignored.
   /o, /output         Specifies the name of the compressed output file.

   /u, /uninstall      Removes saved settings, i.e. cleans
                       up the application footprint.

   /?, /h, /help       Displays this help text.

The interface deliberately takes a single path as argument, because you are then capable of dropping any folder on top of the application (or shortcut, if you make one) using Windows drag-and-drop, since the first argument passed to the application is the dropped folder path.

Grains of Gold

Built Using MVVM and the Dialog Service

The application is built using MVVM, which seems to be on everybody's lips for the moment. Opening dialogs is accomplished with the dialog service from my previous article: Showing Dialogs When Using the MVVM Pattern. This time, the service features a FolderBrowserDialog instead of a OpenFileDialog. The idea of a having a service opening the dialogs still holds for these small applications, no clouds on the horizon yet. Feel free to give the article a glance, and give me your opinion on the idea.

New Way of Writing Properties

The ViewModels are implemented with a new way of writing properties. We usually write a ViewModel property like this:

private string someText;

public string SomeText
  get { return someText; }
    if (someText != value)
      someText = value;

With a little help from some methods, we now can write:

public string SomeText
  get { return Property(() => SomeText); }
  set { Property(() => SomeText, value); }

We no longer have to write the repetitive setter code, and Visual Studio IntelliSense is better at picking up this format than the first containing a string in the OnPropertyChanged method.

The code supporting this new format exists in ViewModelBase:

/// <summary>
/// Gets the value of a property matching the given expression.
/// </summary>
/// <typeparam name="T">The property type.</typeparam>
/// <param name="nameExpression">The expression pointing to the property.</param>
/// <returns>The property value if existing; otherwise default.</returns>
protected T Property<T>(Expression<Func<T>> nameExpression)
  PropertyItem p;
  if (properties.TryGetValue(nameExpression.ToString(), out p))
    return (T)p.Value;

  return default(T);

/// <summary>
/// Sets the value of a property matching the given expression.
/// </summary>
/// <typeparam name="T">The property type.</typeparam>
/// <param name="nameExpression">The expression pointing to the property.</param>
/// <param name="value">The value to set.</param>
protected void Property<T>(Expression<Func<T>> nameExpression, T value)
  // Get the key of the property
  string key = nameExpression.ToString();

  PropertyItem p;
  if (properties.TryGetValue(key, out p))
    // Make sure the property value has changed
    if ((p.Value == null && value == null) || 
        (p.Value != null && p.Value.Equals(value)))

    // Set the new value
    p.Value = value;
    // Create the new property item
    p = new PropertyItem
      Name = GetPropertyName(nameExpression),
      Value = value

    // Add the new propery item
    properties.Add(key, p);

  // Raise property changed event
  OnPropertyChanged(new PropertyChangedEventArgs(p.Name));

/// <summary>
/// Gets the property name of the expression.
/// </summary>
/// <typeparam name="T">The property type.</typeparam>
/// <param name="nameExpression">The name expression.</param>
/// <returns>The property name of the expression.</returns>
private static string GetPropertyName<T>(Expression<Func<T>> nameExpression)
  UnaryExpression unaryExpression = nameExpression.Body as UnaryExpression;

  // Convert name expression into MemberExpression
  MemberExpression memberExpression = unaryExpression != null ?
    (MemberExpression)unaryExpression.Operand :

  return memberExpression.Member.Name;

/// <summary>
/// Class wrapping up the essential parts of a property.
/// </summary>
class PropertyItem
  /// <summary>
  /// Gets or sets the name.
  /// </summary>
  public string Name { get; set; }

  /// <summary>
  /// Gets or sets the value.
  /// </summary>

  public object Value { get; set; }

Algorithm Searching Files and Folders with Exclude Pattern

The .NET framework supports searching for files and folders using DirectoryInfo.GetFiles(string searchPattern) and DirectoryInfo.GetDirectories(string searchPattern), but it doesn't feature one to search using an exclude pattern. When it came to deciding what files and folders are acceptable in a compressed source attachment, I decided that it was easier for a user to state what he/she didn't want rather than specifying what he/she did want.

The following code exists in GetFilesTask and uses LINQ to solve the problem:

/// <summary>
/// Recursive method finding all files from a directory and its sub-directory.
/// </summary>
/// <param name="directory">The directory.</param>
/// <param name="excludePatterns">The file and directory exclude pattern.</param>
private IEnumerable<string> RecursiveGetFiles(DirectoryInfo directory,
  string[] excludePatterns)
  // Find files not matching the exclude patterns
  IEnumerable<FileInfo> files =
    (from file in directory.GetFiles()
     select file)
    .Except(GetExcludedFiles(directory, excludePatterns), new FileInfoEqualityComparer());

  // Yield files not matching the exclude patterns
  foreach (FileInfo file in files)
    yield return file.FullName;

  // Find directories not matching the exclude patterns
  IEnumerable<DirectoryInfo> subDirectories =
    (from subDirectory in directory.GetDirectories()
     select subDirectory)
    .Except(GetExcludedDirectories(directory, excludePatterns),
      new DirectoryInfoEqualityComparer());

  // Search files in sub-directories not matching the exclude pattern
  foreach (DirectoryInfo subDirectory in subDirectories)
    // Yield all files not matching the exclude patterns
    foreach (string file in RecursiveGetFiles(subDirectory, excludePatterns))
      yield return file;

/// <summary>
/// Gets the excluded files in a specified directory.
/// </summary>
/// <param name="directory">The directory.</param>
/// <param name="excludePatterns">The file exclude pattern.</param>
private IEnumerable<FileInfo> GetExcludedFiles(DirectoryInfo directory,
  string[] excludePatterns)
    from excludePattern in excludePatterns
    from filesMatchingExcludePattern in directory.GetFiles(excludePattern)
    select filesMatchingExcludePattern;

/// <summary>

/// Gets the excluded sub-directories in a specified directory.
/// </summary>
/// <param name="directory">The directory.</param>
/// <param name="excludePatterns">The directory exclude pattern.</param>
private IEnumerable<DirectoryInfo> GetExcludedDirectories(DirectoryInfo directory,
  string[] excludePatterns)
    from excludePattern in excludePatterns
    from directoriesMatchingExcludePattern in directory.GetDirectories(excludePattern)
    select directoriesMatchingExcludePattern;

class FileInfoEqualityComparer : IEqualityComparer<FileInfo>

  public bool Equals(FileInfo x, FileInfo y)
    return x.FullName.Equals(y.FullName);

  public int GetHashCode(FileInfo obj)
    return obj.FullName.GetHashCode();

class DirectoryInfoEqualityComparer : IEqualityComparer<DirectoryInfo>
  public bool Equals(DirectoryInfo x, DirectoryInfo y)
    return x.FullName.Equals(y.FullName);

  public int GetHashCode(DirectoryInfo obj)
    return obj.FullName.GetHashCode();


  • (20 December 2009)
    • Console
      • Implemented a console interface
      • Implemented uninstall
    • UI
      • Source path is editable and handles validation
      • Changed default path
      • Fixed initial focus
      • Added additional default ignore patterns
  • (25 October 2009)
  • (7 July 2009)
    • Initial version


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer Axis Communications
Sweden Sweden
Got my first computer in the 90's and loved it even though it sounded like a coffeemaker.

Now getting paid for designing cool applications, and drinks the coffee instead of listening to it being made.

You may also be interested in...


Comments and Discussions

GeneralMy vote of 5 Pin
SAKryukov9-Jan-11 13:58
memberSAKryukov9-Jan-11 13:58 
GeneralRe: My vote of 5 Pin
disore10-Jan-11 7:56
memberdisore10-Jan-11 7:56 
GeneralAlternative to Plossum Pin
SAKryukov9-Jan-11 13:56
memberSAKryukov9-Jan-11 13:56 
GeneralRe: Alternative to Plossum Pin
disore10-Jan-11 7:55
memberdisore10-Jan-11 7:55 
GeneralRe: Alternative to Plossum Pin
SAKryukov10-Jan-11 13:32
memberSAKryukov10-Jan-11 13:32 
QuestionMisuse of SVN? Pin
SAKryukov25-Oct-09 14:34
memberSAKryukov25-Oct-09 14:34 
First of all, your attempt to help avoiding non-source code files in the submission set is quite useful.
I personally meet too many developers who do not even understand which files emerging during developing work are part of the source code, and which are not; this is really bad and question the very ownership of the code. Some of such developers even submit their articles for CodeProject or elsewhere.

But then, I was wondering if you're using any revision decent control system like Subversion, because it would streamlines whole process and virtually eliminate this problem.
To my surprise, I spotted in you article words about stripping SVN sub-directories. Then, do you really know who use revision control?

Look, you're creating artificial problems out of something designed to avoid them in first place!
Subversion is designed to eliminated unwanted files from the pure source, not to create them -- unless somebody abuses the tool.

First, you should set up your system to ignore unwanted files and sub-directories from attempted commits.
TortoiseSVN client offers convenient global ignore pattern to ignore all those "bin", "obj", "*.sln.cache", "*.user", "*.ncb", "*.suo", "Debug", "Release" and the like.
Secondly, why would anyone ever pack and submit a local checked-out development directory? To extract pure source, Subversion provides correct command called "Export".
RTFM, if I may say so...

Thank you.

Sergey A Kryukov

AnswerRe: Misuse of SVN? Pin
disore26-Oct-09 1:45
memberdisore26-Oct-09 1:45 
GeneralRe: Misuse of SVN? Pin
SAKryukov10-Nov-09 8:32
memberSAKryukov10-Nov-09 8:32 
GeneralRe: Misuse of SVN? Pin
disore11-Nov-09 8:22
memberdisore11-Nov-09 8:22 
GeneralRe: Misuse of SVN? Pin
SAKryukov11-Nov-09 12:26
memberSAKryukov11-Nov-09 12:26 
GeneralWhat to improve [modified] Pin
SAKryukov12-Nov-09 6:05
memberSAKryukov12-Nov-09 6:05 
GeneralRe: What to improve Pin
disore21-Nov-09 9:02
memberdisore21-Nov-09 9:02 
GeneralRe: What to improve Pin
disore20-Dec-09 11:53
memberdisore20-Dec-09 11:53 
GeneralVery nice (Re: What to improve) Pin
SAKryukov27-Dec-09 16:19
memberSAKryukov27-Dec-09 16:19 
GeneralRe: Very nice (Re: What to improve) Pin
disore28-Dec-09 5:23
memberdisore28-Dec-09 5:23 
GeneralTwo more improvements Pin
SAKryukov12-Nov-09 6:57
memberSAKryukov12-Nov-09 6:57 
GeneralRe: Two more improvements Pin
disore12-Nov-09 9:17
memberdisore12-Nov-09 9:17 
GeneralRe: Two more improvements Pin
disore21-Nov-09 9:03
memberdisore21-Nov-09 9:03 
Generalthe analog Pin
Cuchuk Sergey20-Jul-09 2:30
memberCuchuk Sergey20-Jul-09 2:30 
GeneralRe: the analog Pin
disore20-Jul-09 2:55
memberdisore20-Jul-09 2:55 
Generalworks BUT complicated!! Pin
kidzopa14-Jul-09 8:36
memberkidzopa14-Jul-09 8:36 
GeneralRe: works BUT complicated!! Pin
disore14-Jul-09 9:06
memberdisore14-Jul-09 9:06 
GeneralRe: works BUT complicated!! Pin
kidzopa14-Jul-09 10:46
memberkidzopa14-Jul-09 10:46 
GeneralFails to download Pin
Johnno9-Jul-09 8:54
memberJohnno9-Jul-09 8:54 
GeneralRe: Fails to download Pin
disore9-Jul-09 9:53
memberdisore9-Jul-09 9:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.180314.2 | Last Updated 20 Dec 2009
Article Copyright 2009 by FantasticFiasco
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid