воскресенье, 12 сентября 2010 г.

Многоязычные установщики MSI

Буквально вчера зарегился на StackOverflow, и обнаружил любопытный вопрос по Microsoft Installer. В результате поиска в документации, книжках и интернете, удалось установить: оказывается, создание многоязычных msi-установщиков возможно! Причем, без всяких bootstrapper'ов.

Хитрость заключается в использовании embedded transforms и недокументированной возможности Windows Installer.

MSI Transforms

Во-первых, что нужно знать: есть такая утилита, msitran.exe, которая создает трансформации msi.

Сразу о том, где её достать. Утилита входит в состав Windows 7 SDK. Причем, на microsoft.com доступен онлайн-установщик весом 500Кб, скачав который, вы можете выбрать состав установки, ограничив размер закачки всего лишь до 40Мб (весь SDK весит, конечно же, намного больше).


После установки, утилита msitran.exe обнаруживается в папке C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin:


Теперь, для создания трансформации, достаточно запустить:
msitran -g {base.msi} {ref.msi} {transform.mst}
, и в результате получаем transform.mst, в который представляет собой "разность" base.msi и ref.msi.

В будущем, чтобы запустить установку ref.msi, имея base.msi и transform.msi, достаточно выполнить msiexec и задать при этом свойство TRANSFORMS:
msiexec /i base.msi TRANSFORMS=transform.mst
Но распространять несколько файлов вместо одного - неудобно. Поэтому, трансформацию transform.mst обычно встраивают в base.msi, используя следующую команду:
cscript emb.vbs base.msi transform.mst
Взять скрипт Emb.vbs можно на MSDN. Как видно из исходного кода, скрипт просто помещает файл в SubStorage.

В дальнейшем, встроенную трансформацию можно запускать, добавляя перед именем файла двоеточие. Пример:
msiexec /i base.msi TRANSFORMS=:transform.mst
Расширение можно опускать:
msiexec /i base.msi TRANSFORMS=:transform
Ну всё, с основами трансформаций вроде разобрались.

Многоязычные установщики

Обычная практика в случае локализованных программ - это создавать по одному msi-файлу на каждую локализацию. К примеру, product_en.msi, product_ru.msi, и т.д. Соответственно, довольно логично сделать переключение между языками через трансформации.

Итак, в идеале, хотелось бы, чтобы свойство TRANSFORMS было доступно внутри установщика. И вместо того, чтобы заставлять пользователя прописывать командную строку, мы бы могли сами, в процессе выполнения установки, определить (каким-нибудь способом), какую именно трансформацию использовать.

Но... трансформации применяются к самому msi, и это происходит ДО его запуска, а значит, если msi уже запущен, то никаких трансформаций к нему применить уже не получится, сколько бы мы не изменяли свойство TRANSFORMS. Так что, все эти идеалы терпят поражение.

И всё-таки, многоязычные установщики - реальность. На InstallSite.org мне удалось обнаружить следующую статью:

Читать обязательно! Благо, на русском языке.

Вкратце, суть статьи в следующем: оказывается, существует для многоязычных установщиков специальная недокументированная возможность в Microsoft Installer, и чтобы её использовать, нужно просто особым образом назвать SubStorage, в котором сохраняется mst. А именно, имя SubStorage должно равняться lcid требуемого языка. К примеру, для русского - 1049, для английского - 1033, и т.д.

Кроме того, в самом msi следует указать свойство Package.Languages, перечислив в нем всё поддерживаемые установщиком языки через запятую.

В этом случае,  язык установщика будет определяться автоматически, исходя из текущей локали операционной системы, на которой осуществляется установка.

Кстати, упомянутый в статье скрипт wisubstg.vbs - это аналог уже рассмотренного выше emb.vbs. Исходный текст этого скрипта можно опять же, найти на MSDN.

Автоматизировать создание многоязычного установщика можно с помощью cmd-файлов. Пример, как это сделать, при использовании WiX, очень хорошо описан на GeekTieGuy.

Комментариев нет:

Отправить комментарий

Внимание! Реклама и прочий спам будут беспощадно удаляться.