> проекты > компоненты инфраструктуры
Компонент для модификации ресурса Version (информация о версии DLL или EXE)

Введение

       При распространении дистрибутивов ваших проектов может возникнуть необходимость обновлять информацию о версии dll и exe-модулей. Однако, ручное изменение информации о версии возможно только посредством среды разработки (например, Visual Studio) или специализированных программ изменения ресурсов (например, exeScope), если вы меняете информацию о версии библиотек, не имея возможности скомпилировать модуль. Для автоматизированного выпуска сборок вашего продукта может потребоваться программный способ изменения информации о версии.

      Реализация данной задачи стала мне более интересной после того, как я не обнаружил функций противоположных по смыслу GetFileVersionInfo (например, SetFileVersionInfo) и VerQueryValue в Win32 API. Модификация ресурса с версией (VS_VERSION_INFO) оказалась невозможной средствами Win32 API. Для устранения этого пробела мной был разработан класс-обертка, который эмулирует структуру ресурса с информацией о версии и позволяет модифицировать поля этой структуры. Далее приводится пример использования класса-обертки class VersionInfo:

#include "vinfo.h"

using namespace vi;

class YourOwnErrorHandler
{
public:
	void error(LPCTSTR lpszErrorText) {
		throw lpszErrorText;
	}
};

void main(int argc, char* argv[])
{
	VersionInfo<VIParserSimple, YourOwnErrorHandler> vi;

	try {
		if(!vi.load(argv[1])) return -1;
			
		// change file version info
		vi[VIH_FILEVERSION] = _L("1, 2, 3, 4");

		// change product name
		vi[VI_PRODUCTNAME] = _L("Your cool program name");

		VIItem &item = vi[_L("OriginalFilename")];
			
		if(item == VIItem::dummy);
			// the item was not found

		vi.update();
	}
	catch(LPCTSTR lpszError)
	{
		printf("error: %s", lpszError);
	}
}
     Целью разработки этого класса-обертки являлась максимальная простота использования с точки зрения программиста C++, вы работает с информацией о версии как с ассоциативным массивом, некоторые значения которого целочисленные, некоторые строковые (unicode). Однако, информация о версии настолько насыщена различными тонкими моментами, что в дальнейшем последуют обновления данного класса.
     С академической точки зрения, в данном классе успешно реализована идиома стратегий (Alexandrescu, 2002), а также примеры определения оператора =, оператора преобразования типов, примеры использования STL.
Специальный случай
      Однако, с изменением информации о версии в некоторых случаях возникают забавные ситуации, которые не позволяют использовать также и стандартного механизма изменения ресурсов в приложении. Так, например, разработчики PowerBuilder (видимо PowerSoft, купленная в последствии Sybase) приняли решение хранить в ресурсе о версии, какую-то дополнительную информацию. Если попытаться применить по назначению вышеописанный класс для исполняемого .exe-модуля, сформированного самой средой или при помощи PBORCA (API для регенрации и компоновки библиотек), то размер этого модуля уменьшится почти в двое.

      Для разрешения этой проблемы был разработан класс-наследник VersionInfoBinary<...>, интерфейс которого унаследован от VersionInfo<...>, а реализация отличается тем, что не используютcя механизмы Win32 API для обновления ресурсов, а модифицируется ресурс непосредственно в .exe-модуле (непосредственная модификация файла). Данный подход отлично работает в описанном случае, однако, имеет некоторое ограничение - размер файла зачастую нельзя увеличить (за счет информации о версии). Разработчики PowerBuilder как-будто специально подготовили почву для изменения информации о версии - все дело в том, что поле Copyright содержит довольно длинную и никчемную строку, местом из-под которой вы и можете воспользоваться (Copyright сделать поменьше, а остальные поля - побольше).

Класс-обертка доступен для скачивания на странице Download

Компонент модификации инфомрации о версии
      Для использования в инфраструктурных бизнес-процессах (например, выпуск сборок, использования инсталляторов) я разработал COM-обертку для модификации информации о версии как посредством Win32 API, так и при помощи непосредственной модификации исполняемого файла (см. предыдущий раздел). Пользоваться компонентом очень просто: вы загружаете информацию о версии (load), а затем модифицируете поля этой структуры, после чего изменения автоматически применяются.
Описание интерфейса
  • load([in] BSTR name) - загружает информацию о версии.
  • getProperty([in] BSTR name, [out, retval] BSTR *pVal) - возвращает значение поля структуры ресурса версии по имени поля.
  • setProperty([in] BSTR name, [in] BSTR val) - установка значения поля структуры ресурса версии по имени поля.
  • Mode - свойство, переключающее режим обновления информации о версии: 0 (умолч.) - посредством Win32 API (VersionInfo), 1 - посредством непосредственной модификации файла (VersionInfoBinary).
  • FileVersion - свойство, соответствующее полю структуры.
  • ProductVersion - свойство, соответствующее полю структуры.
  • Description - свойство, соответствующее полю структуры.
  • Copyright - свойство, соответствующее полю структуры.
  • CompanyName - свойство, соответствующее полю структуры.
  • InternalName - свойство, соответствующее полю структуры.
  • ProductName - свойство, соответствующее полю структуры.
  • Comments - свойство, соответствующее полю структуры.
  • LegalTrademarks - свойство, соответствующее полю структуры.
  • OriginalFilename - свойство, соответствующее полю структуры.
  • SpecialBuild - свойство, соответствующее полю структуры.
    Идентификация
  • ProgID
  • IPM.VersionInfo
  • Потоковая модель
  • Apartment
  • CLSID
  • {6869846A-588B-40BB-97CB-0048DB57BED7}
  • Версия
  • 1

    Компонент доступен для скачивания на странице Download

     Evgeny Savitsky © 2002-2003