Почему MST не включает файлы с различным содержанием - PullRequest
2 голосов
/ 15 сентября 2011

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

Каждый из локализованных установщиков отлично работает как автономный и устанавливаетлокализованные файлы, такие как eula.pdf.

Я надеюсь, что мне просто не хватает флажка на этапе генерации преобразования (или, возможно, используется неправильный инструмент?)

Процесс запускаетсяимея набор инсталляторов 1 для каждого языка.

Чтобы собрать каждый инсталлятор, мы «освещаем», используя опцию -b "folder" и -loc "folder", чтобы указать каждый язык, который включает некоторое альтернативное содержимое файла, такое как лицензия.pdf.

Файлы для локализации имеют общее имя источника

<File Id='License.pdf' Name='eula.pdf' Source='License(EULA).pdf' KeyPath='yes'/>
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />

Папки, например,

en-US/License(EULA).pdf
en-US/License.rtf
en-US/Product.wxl
fr-FR/License(EULA).pdf
fr-FR/License.rtf
fr-FR/Product.wxl

Есть также некоторые файлы, такие как binary.dll.и binary.exe, которые не локализованы и одинаковы для всех MSI - не ожидайте увидеть их в MST.

Следующим шагом в процессе является созданиеразница MST между базовым языком (английским) и каждым другим языком.Использование Windows\v7.1\Bin\MsiTran.exe из Window SDK

MST выглядит немного маловато для изменения содержимого.

Объединение всех файлов MST в один установщик с использованием Windows\v7.1\Samples\sysmgmt\msi\scripts\wisubstg.vbs

При установке на языке, отличном от английского, весь пользовательский интерфейс программы установки, включая версию лицензии rtf, локализован, но файл eula.pdf на диске всегда является базовым английским языком.

Использование задач Ant-dotnet длязапустить сборку (если она имеет значение) Задача сборки MSI

    <wix mode="light" target="${outlocation}\${lang.folder}\my.msi" wixHome="${wixhome}">
        <lightArg line="-b &quot;${location}&quot;"/> <!-- provide the location of the signable binaries -->
        <lightArg line="-b &quot;${msiwixsource}\Localisation\${lang.folder}&quot;"/> <!-- provide the location of the localisation -->
        <lightArg line="-sice:ICE57"/>
        <lightArg line="-cultures:${lang.culture}"/>
        <lightArg line="-loc &quot;${msiwixsource}\Localisation\${lang.folder}\Product.wxl&quot;"/>
        <lightArg line="-ext &quot;${wixhome}\WixUtilExtension.dll&quot;"/>
        <lightArg line="-ext &quot;${wixhome}\WixUIExtension.dll&quot;"/>
        <lightArg line="-ext &quot;${wixhome}\WixFirewallExtension.dll&quot;"/>
        <lightArg line="-ext &quot;${wixhome}\WixNetFxExtension.dll&quot;"/>
        <sources dir="${msiwixobjects}">
          <include name="*.wixobj"/>
        </sources>
        <moresources dir="${msiwixsource}\Localisation\${lang.folder}">
          <include name="*"/>
        </moresources>
        <moresources dir="${location}">
          <include name="binary.dll,binary.exe"/>
        </moresources>
    </wix>

Задача преобразования

    <exec executable="${windowsSDKBin}">
        <arg value="-g"/>
        <arg value="${outlocation}\en-US\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\my.mst"/>
    </exec>

Задача перепаковки

    <exec executable="cscript">
        <arg value="${windowsSDKMsi}"/>
        <arg value="${outlocation}\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\my.mst"/>
        <arg value="${lang.id}"/>
    </exec>

Product /@Language = "! (Loc.Lang)", указанный в Product.wxl для английского языка, мы перечислили все 1033,1028,1029,1031,1036,1040,1041,1043,1045,1046,2052,3082 для других языков, только специфические, такие как 1036 для fr-FR

1 Ответ

2 голосов
/ 16 сентября 2011

Хорошо, так что после нескольких дней поиска я нашел статью, которая описывает проблему. Как локализовать графический интерфейс установки и доставлять локализованные файлы с помощью MST .

Проблема в том, что MST не содержит элементов таблицы '_Streams', в которых хранятся CAB-файлы.

Вы можете пойти несколькими путями из этого -

1) сделать несколько записей файлов и компонентов для разных языков с условным включением на основе языка или культуры

Это означает, что вы должны изменить свои wxs, если хотите изменить поддерживаемые языки.

<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***'>
  <Condition><![CDATA[(ProductLanguage = "1033")]]></Condition>
  <File Id='License.pdf' Name='!(loc.EULA)' Source='en-US\License(EULA).pdf' KeyPath='yes'/>
</Component>
<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***'>
  <Condition><![CDATA[(ProductLanguage = "1046")]]></Condition>
  <File Id='License.pdf' Name='!(loc.EULA)' Source='pt-BR\License(EULA).pdf' KeyPath='yes'/>
</Component>
... add a new block each time you add a language, changes to files have to be duplicated for every block.

Что, в свою очередь, означает перекомпиляцию, а не просто перекомпоновку wxl. Вам все еще нужно упаковать файлы MST.

2) вручную настроить локализованный MSI

Согласно Как локализовать графический интерфейс установки и доставлять локализованные файлы с помощью MST .

3) автоматическое разбиение локализованных элементов в отдельный CAB с локализованным именем

Вместо перекомпиляции это перекомпоновка и дополнительный процесс для управления файлами CAB. Дополнительный процесс к - * распакуйте CAB-файл (ы) вместе с генерацией MST,
* затем при слиянии mst также добавьте cab-файлы.

Добавить дополнительный носитель с локализованным именем - я использую идентификатор lang, как это удобно

<Media Id="2" Cabinet="localised_!(loc.LANG).cab" EmbedCab="yes" />

Изменение локализованных файлов / компонентов для новых носителей

<Component Directory="INSTALLDIR" Id='EULADoc' Guid='***' DiskId='2'>
  <File Id='License.pdf' Name='!(loc.EULA)' Source='License(EULA).pdf' KeyPath='yes'/>
</Component>

При генерации преобразований с использованием MSITran.exe также экспортируйте локализованные CAB-файлы с использованием MsiDb.Exe При объединении преобразований в базовый MSI с использованием WiSubStg.vbs также добавьте файлы CAB в _Streams с помощью WiStram.vbs

Я выбрал вариант 3 Я надеюсь, что кто-то еще найдет это полезным. Примечание:

  • Я не пишу много ANT, поэтому не стесняйтесь предлагать
  • мы создаем неподписанную для тестирования и подписанную версию для выпуска, поэтому необходимо настроить места ввода / вывода для поиска двоичных файлов и msi.

и сборка муравья выглядит примерно так:

<taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="buildjars"/>
<taskdef name="for" classname="net.sf.antcontrib.logic.ForTask" classpathref="buildjars"/> 
<taskdef name="wix" classname="org.apache.ant.dotnet.wix.WixTask" classpathref="buildjars"/>

<property name="wixhome" value="C:\Program Files (x86)\Windows Installer XML v3.5\bin"/>

<property name="binarieslocation" value="build"/>
<property name="msiwixsource" value="install"/>
<property name="msiwixobjects" value="${msiwixsource}\obj\x64\Release"/>
<!-- <dirname property="windowsSDK" file="C:\Program Files\Microsoft SDKs\Windows\v7.1\"/> Ant doesn't like path segments with . -->
<property name="windowsSDKBin" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\MsiTran.exe"/>
<property name="windowsSDKCab" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\MsiDb.Exe"/>
<property name="windowsSDKMsiStorage" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\sysmgmt\msi\scripts\WiSubStg.vbs"/>
<property name="windowsSDKMsiStream" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\sysmgmt\msi\scripts\WiStream.vbs"/>
<property name="windowsSDKMsiLanguages" location="C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\sysmgmt\msi\scripts\WiLangId.vbs"/>  

<property name="cultureBase" value="en-US:en-US:1033"/>
<property name="cultures" value="pt-BR:pt-BR:1046,cs-CZ:en-US:1029"/> 

<target name="installer">
    <echo>Building ${culture} msi using binaries in "${location}"...</echo>
    <propertyregex property="lang.folder" input="${culture}" regexp="(.*):(.*):(.*)" select="\1"/>
    <propertyregex property="lang.culture" input="${culture}" regexp="(.*):(.*):(.*)" select="\2"/>

<wix mode="light" target="${outlocation}\${lang.folder}\my.msi" wixHome="${wixhome}">
    <lightArg line="-b &quot;${location}&quot;"/> <!-- provide the location of the signable binaries -->
    <lightArg line="-b &quot;${msiwixsource}\Localisation\${lang.folder}&quot;"/> <!-- provide the location of the localisation -->
    <lightArg line="-sice:ICE57"/>
    <lightArg line="-cultures:${lang.culture}"/>
    <lightArg line="-loc &quot;${msiwixsource}\Localisation\${lang.folder}\Product.wxl&quot;"/>
    <lightArg line="-ext &quot;${wixhome}\WixUtilExtension.dll&quot;"/>
    <lightArg line="-ext &quot;${wixhome}\WixUIExtension.dll&quot;"/>
    <sources dir="${msiwixobjects}">
      <include name="*.wixobj"/>
    </sources>
    <moresources dir="${msiwixsource}\Localisation\${lang.folder}">
      <include name="*"/>
    </moresources>
    <moresources dir="${location}">
      <include name="binary.dll,binary.exe"/>
    </moresources>
</wix>

</target>

<target name="checkTransform" depends="installer">
    <uptodate property="transform.notRequired" targetfile="${outlocation}\${culture}\my.mst" >
        <srcfiles dir= "${outlocation}\en-US\" includes="my.msi"/>
        <srcfiles dir= "${outlocation}\${lang.culture}\" includes="my.msi"/>
    </uptodate>
</target>

<target name="transform" depends="checkTransform" unless="transform.notRequired">
    <echo>Building ${culture} mst ...</echo>
    <propertyregex property="lang.folder" input="${culture}" regexp="(.*):(.*):(.*)" select="\1"/>
    <propertyregex property="lang.id" input="${culture}" regexp="(.*):(.*):(.*)" select="\3"/> 

    <!-- Generate the mst 'diff' file - this does not include exporting the language specific cab file to match -->
    <exec executable="${windowsSDKBin}">
        <arg value="-g"/>
        <arg value="${outlocation}\en-US\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\my.mst"/>
    </exec>

    <!-- Exporting the language specific cab file to match -->
    <delete file="localised_${lang.id}.cab" />
    <delete file="${outlocation}\${lang.folder}\localised_${lang.id}.cab" />
    <exec executable="${windowsSDKCab}">
        <arg value="-d"/>
        <arg value="${outlocation}\${lang.folder}\my.msi"/>
        <arg value="-x"/>
        <arg value="localised_${lang.id}.cab"/>
    </exec>
    <move file="localised_${lang.id}.cab" tofile="${outlocation}\${lang.folder}\localised_${lang.id}.cab"/>
</target>

<!-- Target to build MSIs using unsigned binaries -->
<target name="MSIs">
    <!-- we always need english as it is the base multilingual -->
    <antcall target="installer">
        <param name="culture" value="${cultureBase}" />
        <param name="location" value="${location}" />
        <param name="outlocation" value="${outlocation}" />
    </antcall>
    <!-- build the different cultures and make transforms 
    parallel="true" sometimes fails-->
    <for list="${cultures}" param="culture" >
      <sequential>
        <antcall target="transform">
            <param name="culture" value="@{culture}" />
            <param name="location" value="${location}" />
            <param name="outlocation" value="${outlocation}" />
        </antcall>
      </sequential>
    </for>
</target>

<!-- depends="transform" -->
<target name="transformRepack" >
    <echo>Packing ${culture} mst into multilingual installer...</echo>
    <propertyregex property="lang.folder" input="${culture}" regexp="(.*):(.*):(.*)" select="\1"/>
    <propertyregex property="lang.id" input="${culture}" regexp="(.*):(.*):(.*)" select="\3"/> 

    <exec executable="cscript">
        <arg value="${windowsSDKMsiStream}"/>
        <arg value="${outlocation}\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\localised_${lang.id}.cab"/>
        <arg value="localised_${lang.id}.cab"/>
    </exec> 
    <exec executable="cscript">
        <arg value="${windowsSDKMsiStorage}"/>
        <arg value="${outlocation}\my.msi"/>
        <arg value="${outlocation}\${lang.folder}\my.mst"/>
        <arg value="${lang.id}"/>
    </exec>
</target>

<target name="MSIMulti" depends="MSIs">
    <echo>Making multilingual installer...</echo>

    <copy file="${outlocation}\en-US\my.msi" todir="${outlocation}"/>

    <for list="${cultures}" param="culture">
      <sequential>
        <antcall target="transformRepack">
            <param name="culture" value="@{culture}" />
            <param name="location" value="${location}" />
            <param name="outlocation" value="${outlocation}" />
        </antcall>
      </sequential>
    </for>
    <!-- report what was packed -->
    <propertyregex property="lang.ids" input="${cultures}" regexp="([^:,]*):([^:]*):([^,]*)" replace="\3" global="true" defaultvalue="failed"/> 
    <echo/>
    <echo>Multilingual installer should include transform language ids </echo>
    <echo>${lang.ids}</echo>
    <echo>Multilingual installer reports transform language ids...</echo>
    <exec executable="cscript">
        <arg value="${windowsSDKMsiStorage}"/>
        <arg value="${outlocation}\my.msi"/>
    </exec>
    <exec executable="cscript">
        <arg value="${windowsSDKMsiLanguages}"/>
        <arg value="${outlocation}\my.msi"/>
        <arg value="Package"/>
        <arg value="1033,${lang.ids}"/>
    </exec>
</target>

<target name="UnsignedMSIMulti" >
    <antcall target="MSIMulti">
        <param name="location" value="${binarieslocation}" />
        <param name="outlocation" value="${binarieslocation}" />
    </antcall>
</target>
...