您的位置:首页 > 其它

Wix 安装部署教程(十三) -- 多语言安装包

2015-08-14 08:06 711 查看
这几天摸索WIX的多语言安装包(这里是Wix的setup 工程,不是Bundle),终于走通了,感谢网友uni的指点。WIX的多语言安装包能够根据系统环境自动切换界面语言,你也可以通过命令指定语言。下面我说一说步骤。共4步。

1.设置WixLocalization文件。

Wxl文件就相当于应用程序的资源文件。让我们根据不同的语言来编写不同的文本内容。

' Windows Installer utility to report the language and codepage for a package
' For use with Windows Scripting Host, CScript.exe or WScript.exe
' Copyright (c) Microsoft Corporation. All rights reserved.
' Demonstrates the access of language and codepage values
'
Option Explicit

Const msiOpenDatabaseModeReadOnly     = 0
Const msiOpenDatabaseModeTransact     = 1
Const ForReading = 1
Const ForWriting = 2
Const TristateFalse = 0

Const msiViewModifyInsert         = 1
Const msiViewModifyUpdate         = 2
Const msiViewModifyAssign         = 3
Const msiViewModifyReplace        = 4
Const msiViewModifyDelete         = 6

Dim argCount:argCount = Wscript.Arguments.Count
If argCount > 0 Then If InStr(1, Wscript.Arguments(0), "?", vbTextCompare) > 0 Then argCount = 0
If (argCount = 0) Then
message = "Windows Installer utility to manage language and codepage values for a package." &_
vbNewLine & "The package language is a summary information property that designates the" &_
vbNewLine & " primary language and any language transforms that are available, comma delim." &_
vbNewLine & "The ProductLanguage in the database Property table is the language that is" &_
vbNewLine & " registered for the product and determines the language used to load resources." &_
vbNewLine & "The codepage is the ANSI codepage of the database strings, 0 if all ASCII data," &_
vbNewLine & " and must represent the text data to avoid loss when persisting the database." &_
vbNewLine & "The 1st argument is the path to MSI database (installer package)" &_
vbNewLine & "To update a value, the 2nd argument contains the keyword and the 3rd the value:" &_
vbNewLine & "   Package  {base LangId optionally followed by list of language transforms}" &_
vbNewLine & "   Product  {LangId of the product (could be updated by language transforms)}" &_
vbNewLine & "   Codepage {ANSI codepage of text data (use with caution when text exists!)}" &_
vbNewLine &_
vbNewLine & "Copyright (C) Microsoft Corporation.  All rights reserved."
Wscript.Echo message
Wscript.Quit 1
End If

' Connect to Windows Installer object
On Error Resume Next
Dim installer : Set installer = Nothing
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError

' Open database
Dim databasePath:databasePath = Wscript.Arguments(0)
Dim openMode : If argCount >= 3 Then openMode = msiOpenDatabaseModeTransact Else openMode = msiOpenDatabaseModeReadOnly
Dim database : Set database = installer.OpenDatabase(databasePath, openMode) : CheckError

' Update value if supplied
If argCount >= 3 Then
Dim value:value = Wscript.Arguments(2)
Select Case UCase(Wscript.Arguments(1))
Case "PACKAGE"  : SetPackageLanguage database, value
Case "PRODUCT"  : SetProductLanguage database, value
Case "CODEPAGE" : SetDatabaseCodepage database, value
Case Else       : Fail "Invalid value keyword"
End Select
CheckError
End If

' Extract language info and compose report message
Dim message:message = "Package language = "         & PackageLanguage(database) &_
", ProductLanguage = " & ProductLanguage(database) &_
", Database codepage = "        & DatabaseCodepage(database)
database.Commit : CheckError  ' no effect if opened ReadOnly
Set database = nothing
Wscript.Echo message
Wscript.Quit 0

' Get language list from summary information
Function PackageLanguage(database)
On Error Resume Next
Dim sumInfo  : Set sumInfo = database.SummaryInformation(0) : CheckError
Dim template : template = sumInfo.Property(7) : CheckError
Dim iDelim:iDelim = InStr(1, template, ";", vbTextCompare)
If iDelim = 0 Then template = "Not specified!"
PackageLanguage = Right(template, Len(template) - iDelim)
If Len(PackageLanguage) = 0 Then PackageLanguage = "0"
End Function

' Get ProductLanguge property from Property table
Function ProductLanguage(database)
On Error Resume Next
Dim view : Set view = database.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductLanguage'")
view.Execute : CheckError
Dim record : Set record = view.Fetch : CheckError
If record Is Nothing Then ProductLanguage = "Not specified!" Else ProductLanguage = record.IntegerData(1)
End Function

' Get ANSI codepage of database text data
Function DatabaseCodepage(database)
On Error Resume Next
Dim WshShell : Set WshShell = Wscript.CreateObject("Wscript.Shell") : CheckError
Dim tempPath:tempPath = WshShell.ExpandEnvironmentStrings("%TEMP%") : CheckError
database.Export "_ForceCodepage", tempPath, "codepage.idt" : CheckError
Dim fileSys : Set fileSys = CreateObject("Scripting.FileSystemObject") : CheckError
Dim file : Set file = fileSys.OpenTextFile(tempPath & "\codepage.idt", ForReading, False, TristateFalse) : CheckError
file.ReadLine ' skip column name record
file.ReadLine ' skip column defn record
DatabaseCodepage = file.ReadLine
file.Close
Dim iDelim:iDelim = InStr(1, DatabaseCodepage, vbTab, vbTextCompare)
If iDelim = 0 Then Fail "Failure in codepage export file"
DatabaseCodepage = Left(DatabaseCodepage, iDelim - 1)
fileSys.DeleteFile(tempPath & "\codepage.idt")
End Function

' Set ProductLanguge property in Property table
Sub SetProductLanguage(database, language)
On Error Resume Next
If Not IsNumeric(language) Then Fail "ProductLanguage must be numeric"
Dim view : Set view = database.OpenView("SELECT `Property`,`Value` FROM `Property`")
view.Execute : CheckError
Dim record : Set record = installer.CreateRecord(2)
record.StringData(1) = "ProductLanguage"
record.StringData(2) = CStr(language)
view.Modify msiViewModifyAssign, record : CheckError
End Sub

' Set ANSI codepage of database text data
Sub SetDatabaseCodepage(database, codepage)
On Error Resume Next
If Not IsNumeric(codepage) Then Fail "Codepage must be numeric"
Dim WshShell : Set WshShell = Wscript.CreateObject("Wscript.Shell") : CheckError
Dim tempPath:tempPath = WshShell.ExpandEnvironmentStrings("%TEMP%") : CheckError
Dim fileSys : Set fileSys = CreateObject("Scripting.FileSystemObject") : CheckError
Dim file : Set file = fileSys.OpenTextFile(tempPath & "\codepage.idt", ForWriting, True, TristateFalse) : CheckError
file.WriteLine ' dummy column name record
file.WriteLine ' dummy column defn record
file.WriteLine codepage & vbTab & "_ForceCodepage"
file.Close : CheckError
database.Import tempPath, "codepage.idt" : CheckError
fileSys.DeleteFile(tempPath & "\codepage.idt")
End Sub

' Set language list in summary information
Sub SetPackageLanguage(database, language)
On Error Resume Next
Dim sumInfo  : Set sumInfo = database.SummaryInformation(1) : CheckError
Dim template : template = sumInfo.Property(7) : CheckError
Dim iDelim:iDelim = InStr(1, template, ";", vbTextCompare)
Dim platform : If iDelim = 0 Then platform = ";" Else platform = Left(template, iDelim)
sumInfo.Property(7) = platform & language
sumInfo.Persist : CheckError
End Sub

Sub CheckError
Dim message, errRec
If Err = 0 Then Exit Sub
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
If Not installer Is Nothing Then
Set errRec = installer.LastErrorRecord
If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
End If
Fail message
End Sub

Sub Fail(message)
Wscript.Echo message
Wscript.Quit 2
End Sub


View Code
语法:

WiLangId.vbs "en-us\TestInstaller.msi" Package 1033,1028,2052


执行成功会出现下面的提示框:



这个时候,我们再点击英文的安装包。出现的是中文界面了。因为它已经根据我的系统环境自动做了选择。测试了繁体系统也是ok的。

4.用命令选择语言。

但是,这都还不是完整的多语言。有时候用户需要选择,比如他想再繁体系统中使用简体安装界面,而且我们的安装界面的多语言需要和我们应用程序的多语言同步起来。基于这个需求,我们还是需要在msi文件上包一个壳,先让用户去选择一门语言。那么我们怎么用命令来执行呢?

msiexec有命令:

msiexec /i  en-us\DIAViewSetup.msi TRANSFORMS=transforms\zh-tw.mst


指定在简体系统中使用繁体界面:



这样在我们的C++外壳中就可以根据用户的选择也触发不同的界面。如果用户自己手动去安装,也起码可以根据他当前的系统自动切换语言。

小结:本文没有提供完整的安装包多语言解决方法。仅仅为大家提供了一种我走通了的方法,另外还有许可证书的部分,不同的语言,不同的许可证书,但路径又是不能通过loc的方式来处理的。需要自定义窗口来处理,后面有新的发现我会继续更新。希望对苦逼的WIX学习者带来帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: