Программирование

Exepack.NET 0.02 alpha

Posted in Программирование, Программы on Январь 25th, 2010 by yallie – 2 Comments

Не прошло и года, как я доделал Windows-версию упаковщика Exepack.NET. Правда, помимо интерфейса WinForms тут добавлена еще целая куча разных улучшений.

Консольную и GUI-версии программы вместе с исходниками можно взять на сайте проекта. Среди прочего в исходниках лежит и концептуальная версия (минимальный скелет программы без каких-либо наворотов), по которой можно разобраться, как все это работает. Концептуальная версия описана в нескольких прошлых постах: часть 1, часть 2, часть 3.

Системные требования:

  • .NET Framework версии 2.0 или выше (используется DeflateStream)
  • Windows XP или выше (используются системные процедуры для загрузки ресурсов)

Новые возможности версии 0.02 alpha:

  • Исполняемый файл генерируется с помощью Reflection.Emit
  • Ресурсы иконок и VersionInfo копируются из исходного файла
  • В Windows-версии можно добавлять в список дополнительные сборки для упаковки в тот же исполняемый файл
  • Добавлена защита от дизассемблирования Red Gate .NET Reflector-ом
  • Ну и, разумеется, добавлены новые исправлены старые ошибки.

Справа — скриншот Рефлектора, который пытается декомпилировать упакованный файл. Попытка декомпилировать в C# (и любой другой высокоуровневый язык) приводит к ошибке. Дизассемблирование в IL, разумеется, работает, как и ILDasm (любую программу, которая загружается и запускается под .NET Framework, можно дизассемблировать в IL-код).

P.S. Стоит иметь в виду, что это по-прежнему альфа-версия. Любое использование исключительно на свой страх и риск. Замечания об ошибках и неполадках приветствуются.

Хранилище для временных файлов

Posted in Программирование on Март 6th, 2009 by yallie – Be the first to comment

Мне частенько приходится использовать хранилище для временных файлов (например, чтобы сохранить файлы во временную папку и передать на обработку внешней программе, а в конце работы все почистить). Обычно я каждый раз пишу подобную ерунду заново, чтобы не искать того, что было написано в прошлый раз. Искать — это, во-первых долго, во-вторых лень, а в-третьих иногда оказывается, что искомое лежит не на домашнем компе, а на рабочем. Словом, обычно написать заново выходит быстрее :)

Сегодня я очередной раз написал такой класс-хранилище, и получилось вполне симпатично. Пользоваться им нужно вот так:

using (TempFileManager temp = new TempFileManager())
{
  using (FileStream fs = File.Create(temp["my-temp-file.txt"]))
  {
    // файл my-temp-file.txt создался во временной папке
    // и будет удален вместе с ней
  }
}

Класс TempFileManager создает временную папку…

Декларативный интерфейс

Posted in Программирование on Февраль 14th, 2009 by yallie – Be the first to comment

Декларативный интерфейсДля большинства небольших программ на WinForms отлично подходит дизайнер меню и панелей инструментов. Самый подходящий случай — это небольшая монолитная программка с более-менее фиксированным набором функций. Например, какой-нибудь простой текстовый редактор.

А самый неподходящий вариант — модульная программа, построенная на плагинах. Что если плагин должен иметь возможность добавлять команды в главное меню или кнопки на панель инструментов? Давать плагину доступ к меню небезопасно, поэтому обычно поступают наоборот: программа спрашивает у плагина, какие команды он поддерживает и сама добавляет их в свое меню. Для этого плагин должен поддерживать метод типа GetPluginCommands(), возвращающий коллекцию доступных команд.

В результате…

Exepack.NET, часть 3

Posted in Программирование on Февраль 7th, 2009 by yallie – Be the first to comment

ilmerge_packedС загрузчиком все понятно, осталось сделать сам упаковщик. Задача упаковщика в двух словах такова: определить список файлов, упаковать их, скомпилировать загрузчик и приклеить к нему упакованные файлы в виде ресурсов. Пока я писал загрузчик, мне нужно было делать это вручную, теперь же моя задача это автоматизировать.

Итак, упаковщик работает по такой схеме:

  1. Загружает главную исполняемую сборку (*.exe)
  2. Составляет список используемых библиотек классов (*.dll)
  3. Упаковывает все сборки, сохраняет во временные файлы
  4. Готовит исходник для загрузчика (loader.cs)
  5. Компилирует загрузчик, добавляя временные файлы как ресурсы
  6. Удаляет временные файлы

Список библиотек для упаковки, конечно, можно было бы задавать явно (например, в командной строке) . Но согласитесь, гораздо приятнее, если упаковщик сам его составит, тем более, что это сделать совсем несложно. Стандартный класс-обертка Assembly, который позволяет более-менее успешно манипулировать .NET-сборками, дает возможность получить список модулей, на которые ссылается загруженная сборка: Assembly.GetReferencedAssemblies().

Повторяя этот процесс рекурсивно, мы получим…

Exepack.NET, часть 2

Posted in Программирование on Январь 31st, 2009 by yallie – Be the first to comment

Программа app.exe в дизассемблере ILDASM

Попробуем усложнить задачу. Возьмем какое-нибудь реальное .NET-приложение, которое состоит из нескольких сборок. Как правило, это один EXE-файл и несколько дополнительных DLL-библиотек.

Модули (файлы *.netmodule) я рассматривать не буду, никогда не видел, чтобы ими кто-то пользовался. Я могу ошибаться, но по-моему, в Visual Studio нет для них полноценной поддержки: проекты компилируются в монолитные сборки, а не в набор модулей. Теоретически, конечно, это может быть реализовано по-разному на разных платформах, но я пока не ставил себе цели написать полностью переносимый EXE-упаковщик.

Чтобы не искать готовое приложение, я за минуту написал небольшую программку из двух файлов: app.cs и applib.cs. На картинке показано, как такая программа выглядит в дизассемблере ILDASM (красным выделена ссылка на сборку-библиотеку).

Теперь я модифицирую загрузчик так, чтобы он мог…

Exepack.NET, часть 1

Posted in Программирование on Январь 24th, 2009 by yallie – 1 Comment

Концепция загрузчикаДавно мечтал написать exe-packer — упаковщик для исполняемых файлов. Дурацкая мечта, прямо скажем, но у меня в запасе еще много таких.

Как недавно мне удалось выяснить, написать такой упаковщик для .NET-программ можно за три часа. Наверное, можно и быстрее, но у меня получилось за три с копейками. Это такая приятная особенность .NET: почти все уже сделано до нас.

А сделано до нас вот что:…