Работая в рамках NET Framework 3.5 не нашел понятных и простых в использовании встроенных средств для создания zip архивов. В версии 4.5 такой проблемы нет. Сборка System.IO.Compression содержит класс ZipFile удовлетворяющий меня вполне. Однако в низших версиях указанная сборка содержит только два класса GZipStream и DeflateStream. Есть конечно еще и сборка System.IO.Packaging, но формат генерируемого ею файла zip несколько отличается от стандартного и заточен скорее под XML. Таким образом, встроенных средств работы со стандартными zip файлами в dotNET 3.5 попросту нет. Осознав этот печальный факт я скрипя сердце стал искать сторонние средства. Таких нашлось немало, но я упомяну лишь два из них.
Если платформа dotNET 3.5 не предоставляет разработчику средств для работы с zip файлами, тогда логично поискать такие средства ниже - на уровне операционной системе Windows. Несомненный кандидат на такую роль Shell32 API размещенный в system32\shell32.dll. Эта библиотека умеет делать много чего интересного. Но я рассмотрю лишь ее zip возможности.
Понятно, что библиотека есть. Но она не является управляемой в смысле NET. Поэтому общаться с библиотекой придется по технологии COM Interop. Для этого необходимо создать обертку инкапсулирующую необходимые вызовы и структуры. В проекте C# сделать это пара пустяков. Достаточно в узел References проекта добавить ссылку на COM объект Microsoft Shell Controls And Automation. В результате появиться новое пространство имен Shell32 и файл Interop.Shell32.dll. Теперь можно архивировать. Рассмотрим простой пример - имеется каталог с файлами который требуется запаковать в zip файл. Первым делом создадим пустой zip. Это не совсем очевидная операция генерирует файл с заголовком в 22 байта следующим образом
byte[] bytes = { 80, 75, 5, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
System.IO.File.WriteAllBytes(zip, bytes);
Теперь получим оболочку шела
var shell = new Shell32.Shell();и определим входной и выходной источники
var input = shell.NameSpace(sourceFolder);
var output = shell.NameSpace(zip);
Заметьте, что выходным источником назначен пустой zip файл, sourceFolder - папка с файлами подлежащими архивированию. Далее осталось скопировать файлы в архив
output.CopyHere(input.Items());
Как видно, код создания zip архива из папки прост до неприличия. Однако некоторые тонкости не дадут покоя. Во-первых, метод CopyHere() осуществляется исключительно асинхронно. Это означает, что появляется задача определения конца завершения процесса копирования файлов в архив. Как вариант можно посоветовать сразу после вызова CopyHere() использовать следующую конструкцию
while (output.Items().Count < input.Items().Count)
{
System.Threading.Thread.Sleep(1);
}
Смысл цикла заключается в том, чтобы на каждой итерации сверять количество скопированных в архив файлов с количеством файлов в каталоге источнике. В случае копирования понятно, это количество остается постоянным. Если же файлы из каталога удаляются (например в сценарии перемещения файлов в архив), условие цикла будет другим.
Во-вторых, что более существенно, для корректной работы приложения которое использует Shell32 API, необходимо отслеживать версию ОС и соответствующую ей библиотеку shell32.dll, так как велика вероятность, что в разных осях будут разные версии библиотеки.
Конечно все эти моменты можно учесть, но я решил воспользоваться уже готовым решением в виде DotNetZip библиотеки. Чего и вам желаю...