为什么MST不包含具有不同内容的文件

时间:2011-09-14 23:33:18

标签: ant wix wix3.5

尝试制作多语言安装程序 - 该过程通常正在运行,但似乎无法安装要安装的本地化文件。

每个本地化安装程序都可以作为独立安装程序正常工作,并安装本地化文件,如eula.pdf。

我希望我只是在变换生成步骤中错过了一个标志(或者可能使用了错误的工具?)

通过为每种语言安装一堆安装程序来开始处理。

要构建每个安装程序,我们使用-b "folder"-loc "folder"选项“点亮”以指定包含一些备用文件内容的每种语言,例如licence.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差异。使用Window SDK中的Windows\v7.1\Bin\MsiTran.exe

MST对于内容的变化似乎有点小。

使用Windows\v7.1\Samples\sysmgmt\msi\scripts\wisubstg.vbs

将所有MST文件合并到一个安装程序中

使用非英语语言安装显示整个安装程序UI,包括本地化的许可证的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 for fr-FR

1 个答案:

答案 0 :(得分:2)

好的,经过几天的搜索,我找到了一篇描述这个问题的文章。 How To Localize the Setup GUI and Deliver Localized Files Using a MST

问题是MST没有包含&#39; _Streams&#39;表元素,这是存储CAB文件的地方。

你可以通过几种方式 -

1)制作多个文件&amp;基于语言或文化的条件包含的不同语言的组件条目

这意味着如果您想更改支持的语言,请更改您的wx。

<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

根据How To Localize the Setup GUI and Deliver Localized Files Using a MST

3)自动将本地化项目拆分为具有本地化名称的单独CAB

然后重新编译和管理CAB文件的额外过程,而不是重新编译。 额外流程 -  *提取CAB文件以及生成mst,
 *然后在合并mst时也添加cab文件。

添加一个具有本地化名称的额外媒体 - 我很方便使用lang id

<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生成转换时,还使用MsiDb.Exe导出本地化的CAB文件 使用WiSubStg.vbs将变换合并到基础MSI时,还可以使用WiStram.vbs

将CAB文件添加到_Streams

我选择了3 我希望其他人觉得这很有用。 注意:

  • 我不会写很多ANT,所以随时提供建议
  • 我们为发布版本构建了一个未签名的测试和签名版本,因此需要调整输入/输出位置以查找二进制文件和msi。

并且ant build看起来像下面这样。

<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>