wix toolset: как создать один exe-файл с названием продукта, локализованным для нескольких языков
Я использую WiX v3.9 R2 для создания моего установщика. У меня есть установщик, локализованный на несколько языков, прекрасно работает. Тем не менее, он всегда использует английское имя приложения в программах и функциях, независимо от того, на каком языке установлен формат и язык отображения.
Как мне указать, чтобы оно использовало локализованное имя для моего приложения в разделе "Программы и компоненты"?
Редактировать:
Чтобы уточнить: я думаю, что мне нужен способ изменить атрибут имени пакета (или [WixBundleName]) во время установки, в зависимости от языка пользователя. Это возможно?
Или, в противном случае, как люди в настоящее время используют WiX Bundle и получают имя программы, локализованное в разделе "Программы и компоненты"?
Изменить 2: с сайта WiX:
WixBundleName - получает имя пакета (из Bundle/@Name). Эта переменная также может быть установлена приложением начальной загрузки, чтобы изменить имя пакета во время выполнения.
Похоже, это можно сделать, но как?
Редактировать 3: Вот мой текущий комплект, для справки. Последний пункт в цепочке - это мое заявление.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="Map Creator"
Version="$(var.ProductVersion)"
Manufacturer="FMOsoft"
IconSourceFile="$(var.KarteDir)\assets\logo\ico\icon.ico"
UpgradeCode="[GUID]"
AboutUrl="http://fmosoft.com/MapCreator"
Copyright="Copyright© 2015, FMOsoft">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkSidebarLicense">
<bal:WixStandardBootstrapperApplication
LocalizationFile="$(var.KarteDir)\install\win\L10n\installer\thm_en_us.wxl"
ThemeFile="$(var.KarteDir)\install\win\HyperlinkSidebarTheme_fmosoft.xml"
LogoFile="$(var.KarteDir)\assets\logo\bmp\logo_64.bmp"
LogoSideFile="logoside.bmp"
ShowVersion="yes"
LicenseFile="$(var.KarteDir)\install\license_en.html"
SuppressOptionsUI="yes"
LaunchTarget="[ProgramFiles6432Folder]\FMOsoft\MapCreator\MapCreator.exe"
/>
<!-- WixStdBa requires specific names, at run time, in the temporary .BA1 folder. XML and png file is only needed for layout changes.
Payload/@Name for .wxl must be <lcid>\thm.wxl
Payload/@Name for .xml must be <lcid>\thm.xml AND must also have logo.png in same folder.-->
<Payload Id="theme_en_us" Compressed="yes" Name="1033\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_en_us.wxl"/>
<Payload Id="license_en_us" Compressed="yes" Name="1033\license.html" SourceFile="$(var.KarteDir)\install\license_en.html"/>
<Payload Id="theme_es_es" Compressed="yes" Name="1034\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_es_es.wxl"/>
<Payload Id="license_es_es" Compressed="yes" Name="1034\license.html" SourceFile="$(var.KarteDir)\install\license_es.html"/>
<Payload Id="theme_fr_fr_xml" Compressed="yes" Name="1036\thm.xml" SourceFile="$(var.KarteDir)\install\win\L10n\installer\HyperlinkSidebarTheme_fmosoft_fr.xml"/>
<Payload Id="theme_fr_fr" Compressed="yes" Name="1036\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_fr_fr.wxl"/>
<Payload Id="theme_fr_fr_logo" Compressed="yes" Name="1036\logo.png" SourceFile="$(var.KarteDir)\assets\logo\bmp\logo_64.bmp"/>
<Payload Id="theme_fr_fr_sidelogo" Compressed="yes" Name="1036\logoside.png" SourceFile="$(var.KarteDir)\install\win\logoside.bmp"/>
<Payload Id="license_fr_fr" Compressed="yes" Name="1036\license.html" SourceFile="$(var.KarteDir)\install\license_fr.html"/>
<Payload Id="theme_pt_br" Compressed="yes" Name="1046\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_pt_br.wxl"/>
<Payload Id="license_pt_br" Compressed="yes" Name="1046\license.html" SourceFile="$(var.KarteDir)\install\license_pt.html"/>
<Payload Id="theme_id" Compressed="yes" Name="1057\thm.wxl" SourceFile="$(var.KarteDir)\install\win\L10n\installer\thm_id.wxl"/>
<Payload Id="license_id" Compressed="yes" Name="1057\license.html" SourceFile="$(var.KarteDir)\install\license_id.html"/>
</BootstrapperApplicationRef>
<WixVariable Id="WixStdbaLicenseUrl" Value="license.html" />
<Variable Name="MyProductVersion" Value="$(var.ProductVersion)" />
<!-- There must be a better way to show the localized name of the app in the setup, but this works. -->
<Variable Name="AppName_es" Value="Creador de Mapas"/>
<Variable Name="AppName_fr" Value="Créateur de Carte"/>
<Variable Name="AppName_pt" Value="Criador de Mapas"/>
<Variable Name="AppName_id" Value="Pencipta Peta"/>
<Chain>
<ExePackage SourceFile="vcredist_x64.exe" PerMachine="yes" Permanent="yes" Vital="yes" Compressed="yes" InstallCommand="/quiet /norestart" InstallCondition="VersionNT64"/>
<ExePackage SourceFile="vcredist_x86.exe" PerMachine="yes" Permanent="yes" Vital="yes" Compressed="yes" InstallCommand="/quiet /norestart" InstallCondition="NOT VersionNT64"/>
<PackageGroupRef Id="OldMapEditorPackage"/>
<MsiPackage Vital="yes" SourceFile="$(var.BuildDir)out\map-creator-$(var.Platform).msi" />
</Chain>
</Bundle>
</Wix>
2 ответа
Для этого есть открытый запрос: http://wixtoolset.org/issues/4045/. Это решение позволит вам предоставить ресурсную библиотеку, в которой "Программы и компоненты" будут запрашивать отображаемое имя, поэтому она изменится, если пользователь изменит язык ОС.
Пока кто-то не реализует эту функцию, вы правы, что это можно сделать, установив WixBundleName
переменная. Если вы пишете пользовательский BA, вы бы позвонили IBootstrapperEngine::SetVariableString
,
Если вы используете WixStdBA, вам придется использовать DLL BAFunctions, которая не очень хорошо документирована для вызова этого метода. Здесь есть пример проекта. Обратите внимание, что недавно была добавлена переменная WixStdBALanguageId, которая поможет вам узнать, какой язык используется в данный момент.
Чтобы добавить BAFunctions.dll, просто добавьте его в качестве полезной нагрузки:
<BootstrapperApplicationRef ...>
<Payload Name="BAFunctions.dll" SourceFile="path\to\your.dll" />
</BootstrapperApplicationRef>
В случае, если это полезно, так как мне потребовалось довольно много времени, чтобы понять, вот как я локализовал WixBundleName, чтобы локализовать его в "Программы и компоненты". Это основано на ответе и комментариях Шона Холла.
Это работает с еженедельной сборкой WiX 3.10.0.1519, созданной в четверг, 19 марта 2015 года.
/* This document describes how we build bafunctions.dll.
1. Install the version of WiX you want to use. This is necessary because it sets some environment variables or something,
and provides some .h files needed to get the BAFunctions project to compile.
2. Download the wixXX-debug.zip file from the same page where the WiX installer is for the version of WiX you want.
3. Unzip and browse to [wixXX-debug\src\burn\Samples\bafunctions\ and open the project in Visual Studio 2010.
4. In WixBootstrapperBAFunction.cpp, add our code as shown below.
5. Rebuild solution in Release configuration.
6. copy bafunctions\release\bafunctions.dll to Map Creator build machine, [map_creator]\install\win\[Wix_X.X]
*/
// In WixBootstrapperBAFunction.cpp:
// comment out this line (line 32 in WiX 3.10):
STDMETHODIMP OnDetectComplete() { return S_OK; }
/* uncomment the commented-out OnDetectComplete procedure, and in the section marked
// YOUR CODE GOES HERE
add this code:
*/
LONGLONG lang_id = NULL;
LPWSTR bundle_name = NULL;
LPWSTR platform = NULL;
LPWSTR orig_name = NULL;
// get the language the user is using
BalGetNumericVariable(L"WixStdBALanguageId", &lang_id);
BalExitOnFailure(hr, "Failed to get variable 'WixStdBALanguageId'.");
// log the language id
char msg[66]; // 66 I'm sure is big enough
sprintf_s(msg, 67, "%s%d", "WixStdBALanguageId is ", lang_id);
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg);
/* I don't know how to pass custom variables from the .wxs, so I tried below to use the built-in HelpTelephone.
That doesn't work either - apparently we can only get variables listed in:
http://wixtoolset.org/documentation/manual/v3/bundle/bundle_built_in_variables.html
BalGetStringVariable(L"WixBundleHelpTelephone", &platform);
BalExitOnFailure(hr, "Failed to get WixBundleHelpTelephone variable.");*/
// Since I don't know how to pass a custom variable from the .wxs, I get the @Name attribute of the Bundle (from the .wxs),
// and I parse out the platform.
BalGetStringVariable(L"WixBundleName", &orig_name);
BalExitOnFailure(hr, "Failed to get WixBundleName variable.");
platform = wcsrchr(orig_name, '(');
// log the platform.
char msg5[66]; // 66 I'm sure is big enough
sprintf_s(msg5, 67, "%s%s", "platform is ", platform);
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg5);
// Select the localized bundle name
// I got the language codes from https://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
switch (lang_id) {
case 1036:
case 2060:
case 3084:
case 4108:
case 5132:
case 6156:
case 7180:
case 8204:
case 9228:
case 10252:
case 11276:
case 12300:
case 13324:
case 14348:
case 15372:
case 58380:
// French
bundle_name = L"Créateur de Carte";
break;
case 1057:
// Indonesian
bundle_name = L"Pencipta Peta";
break;
case 1046:
case 2070:
// Portuguese
bundle_name = L"Criador de Mapas";
break;
case 1034:
case 2058:
case 3082:
case 4106:
case 5130:
case 6154:
case 7178:
case 8202:
case 9226:
case 10250:
case 11274:
case 12298:
case 13322:
case 14346:
case 15370:
case 16394:
case 17418:
case 18442:
case 19466:
case 20490:
case 21514:
case 22538:
// Spanish
bundle_name = L"Creador de Mapas";
break;
default:
bundle_name = L"Map Creator";
}
// log the new bundle name.
char msg2[66]; // 66 I'm sure is big enough
sprintf_s(msg2, 67, "%s%s", "bundle_name is ", bundle_name);
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg2);
// append the platform to the end of the bundle name
wchar_t bundle_name_platform[80];
wcscpy_s(bundle_name_platform, bundle_name);
wcscat_s(bundle_name_platform, L" ");
wcscat_s(bundle_name_platform, platform);
// log the final bundle name (which includes the platform)
char msg3[66]; // 66 I'm sure is big enough
sprintf_s(msg3, 67, "%s%s", "bundle_name_platform is ", bundle_name_platform);
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, msg3);
// set the name of our bundle
hr = m_pEngine->SetVariableString(L"WixBundleName", bundle_name_platform);
BalExitOnFailure(hr, "Failed to set WixBundleName variable.");