System.IO.Packaging 名前空間のクラスを使用して、zip ファイルを作成するプログラムを作ってみました。以下のように第1引数で指定したファイルまたはフォルダを第2引数で指定したファイルにzipファイルとして保存します。

ZipPackageSampe.exe C:\test\archivefolder C:\test\archive.zip

Packaging 名前空間は本来 zip ファイルを作成するためのものではなく、Open Packaging Conventions (OPC)に準拠した複数のデータオブジェクトを格納したデータを作成するためのものだそうです。zipファイルには、[Content_Types].xmlというファイルも作成されます。

1. プログラム

Visual Studio を起動してコンソールアプリケーションプロジェクトを作成します。参照の追加で、WindowsBase.dll を追加します。あとは、既定で作成されるProgram.cs を次のように編集します。

using System;
using System.IO;
using System.IO.Packaging;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ZipPackageSample
{
    /// <summary>
    /// System.IO.Packaging 名前空間のクラスを使用して zip ファイルを作成するサンプルプログラム
    /// Open Packaging Conventions (OPC)に準拠した複数のデータオブジェクトを格納したデータを
    /// 作成するためのクラスであり、本来zipファイルを作成するためのものではないことに注意
    /// zipファイルには[Content_Types].xmlというファイルも作成されます。
    /// </summary>
    class Program
    {
        /// <summary>
        /// 第1引数でしたファイルまたはフォルダを、第2引数で指定されたファイル名で
        /// 圧縮を行う
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("[Usage] ZipPacakgeSample 入力ファイルorフォルダ 出力ファイル");
                return;
            }

            Compress(args[0], args[1]);
        }

        /// <summary>
        /// ZipPackageを作成する
        /// </summary>
        /// <param name="input"></param>
        /// <param name="output"></param>
        static void Compress(string input, string output)
        {
            DirectoryInfo root;
            IList<FileSystemInfo> targets = new List<FileSystemInfo>();
            if (File.Exists(input))
            {
                FileInfo f = new FileInfo(input);
                root = f.Directory;
                targets.Add(f);
            }
            else if (Directory.Exists(input))
            {
                DirectoryInfo d = new DirectoryInfo(input);
                if (d.Equals(d.Root)) throw new Exception("ルートは指定できません");
                root = d.Parent;
                targets.Add(d);
            }
            else
            {
                throw new Exception("存在しないファイルです");
            }

            Uri rootUri = new Uri(root.FullName);

            using (Package package = Package.Open(output, FileMode.Create))
            {
                AddPart(package, root, targets);
            }
        }

        private static void AddPart(Package package, DirectoryInfo root, IList<FileSystemInfo> targets)
        {
            foreach (FileInfo file in targets.OfType<FileInfo>())
            {
                string relativePath = file.FullName.Substring(root.FullName.Length + 1);
                Uri relativeUri = new Uri(relativePath, UriKind.Relative);
                Uri partUri = PackUriHelper.CreatePartUri(relativeUri);
                PackagePart part = package.CreatePart(partUri, string.Empty);
                using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
                {
                    CopyStream(fileStream, part.GetStream());
                }
            }

            foreach (DirectoryInfo dir in targets.OfType<DirectoryInfo>())
            {
                List<FileSystemInfo> childs = new List<FileSystemInfo>();
                childs.AddRange(dir.GetFiles());
                childs.AddRange(dir.GetDirectories());
                AddPart(package, root, childs);
            }
        }
        // MSDN のサンプルのユーティリティメソッド
        private static void CopyStream(Stream source, Stream target)
        {
            const int bufSize = 0x1000;
            byte[] buf = new byte[bufSize];
            int bytesRead = 0;
            while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
                target.Write(buf, 0, bytesRead);
        }

    }
}

2. まとめ

今回の説明は以上です。 フリーで公開されているzipライブラリを使用できない場合、アーカイブした圧縮ファイルを作成するには IE に含まれるzipファイルを作成する コンポーネント を使用することが多いのではと思いますが、System.IO.Packaging 名前空間のクラスを使用してzipファイルを作成できるようになります。