Сценарий 1. Создание файла PRI из строковых ресурсов и файлов ресурсов
В этом сценарии мы будем использовать API индексирования ресурсов пакета (PRI), чтобы создать новое приложение для представления пользовательской системы сборки. Цель этой пользовательской системы сборки, помните, заключается в создании файлов PRI для целевого приложения UWP. Таким образом, в рамках этого пошагового руководства мы создадим некоторые примеры файлов ресурсов (содержащих строки и другие виды ресурсов), чтобы представить эти целевые ресурсы приложения UWP.
Новый проект
Начните с создания проекта в Microsoft Visual Studio. Создайте проект консольного приложения Windows Visual C++ и назовите его CBSConsoleApp (для пользовательского консольного приложения сборки).
Выберите x64 в раскрывающемся списке "Платформы решений".
Заголовки, статическая библиотека и dll
API-интерфейсы PRI объявляются в файле заголовка MrmResourceIndexer.h (который установлен в %ProgramFiles(x86)%\Windows Kits\10\Include\<WindowsTargetPlatformVersion>\um\
). Откройте файл CBSConsoleApp.cpp
и добавьте заголовок вместе с другими нужными заголовками.
#include <string>
#include <windows.h>
#include <MrmResourceIndexer.h>
API реализованы в MrmSupport.dll, доступ к которому осуществляется путем связывания со статической библиотекой MrmSupport.lib. Откройте свойства проекта, нажмите кнопку "Входные данные компоновщика>", измените дополнительныеdependencies и добавьте.MrmSupport.lib
Создайте решение, а затем скопируйте MrmSupport.dll
из C:\Program Files (x86)\Windows Kits\10\bin\<WindowsTargetPlatformVersion>\x64\
папки выходных данных сборки (вероятно C:\Users\%USERNAME%\source\repos\CBSConsoleApp\x64\Debug\
).
Добавьте следующую вспомогающую функцию CBSConsoleApp.cpp
, так как нам потребуется.
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
// Set a breakpoint on this line to catch Win32 API errors.
throw new std::exception();
}
}
main()
В функции добавьте вызовы для инициализации и неинициализации COM.
int main()
{
::ThrowIfFailed(::CoInitializeEx(nullptr, COINIT_MULTITHREADED));
// More code will go here.
::CoUninitialize();
}
Файлы ресурсов, принадлежащие целевому приложению UWP
Теперь нам потребуется несколько примеров файлов ресурсов (содержащих строки и другие виды ресурсов) для представления ресурсов целевого приложения UWP. Конечно, они могут находиться в любом месте файловой системы. Но для этого пошагового руководства будет удобно поместить их в папку проекта CBSConsoleApp, чтобы все было в одном месте. Эти файлы ресурсов необходимо добавить только в файловую систему; Не добавляйте их в проект CBSConsoleApp.
В той же папке, содержащейся CBSConsoleApp.vcxproj
, добавьте новую вложенную папку с именем UWPAppProjectRootFolder
. В этой вложенной папке создайте эти примеры файлов ресурсов.
\UWPAppProjectRootFolder\sample-image.png
Этот файл может содержать любое изображение PNG.
\UWPAppProjectRootFolder\resources.resw
<?xml version="1.0"?>
<root>
<data name="LocalizedString1">
<value>LocalizedString1-neutral</value>
</data>
<data name="LocalizedString2">
<value>LocalizedString2-neutral</value>
</data>
<data name="NeutralOnlyString">
<value>NeutralOnlyString-neutral</value>
</data>
</root>
\UWPAppProjectRootFolder\de-DE\resources.resw
<?xml version="1.0"?>
<root>
<data name="LocalizedString2">
<value>LocalizedString2-de-DE</value>
</data>
</root>
\UWPAppProjectRootFolder\en-US\resources.resw
<?xml version="1.0"?>
<root>
<data name="LocalizedString1">
<value>LocalizedString1-en-US</value>
</data>
<data name="EnOnlyString">
<value>EnOnlyString-en-US</value>
</data>
</root>
Индексирование ресурсов и создание файла PRI
main()
В функции перед вызовом инициализации COM объявите некоторые строки, которые нам потребуются, а также создайте выходную папку, в которой мы создадим наш PRI-файл.
std::wstring projectRootFolderUWPApp{ L"UWPAppProjectRootFolder" };
std::wstring generatedPRIsFolder{ projectRootFolderUWPApp + L"\\Generated PRIs" };
std::wstring filePathPRI{ generatedPRIsFolder + L"\\resources.pri" };
std::wstring filePathPRIDumpBasic{ generatedPRIsFolder + L"\\resources-pri-dump-basic.xml" };
::CreateDirectory(generatedPRIsFolder.c_str(), nullptr);
Сразу после вызова com инициализации объявите дескриптор индексатора ресурсов, а затем вызовите mrmCreateResourceIndexer для создания индексатора ресурсов.
MrmResourceIndexerHandle indexer;
::ThrowIfFailed(::MrmCreateResourceIndexer(
L"OurUWPApp",
projectRootFolderUWPApp.c_str(),
MrmPlatformVersion::MrmPlatformVersion_Windows10_0_0_0,
L"language-en_scale-100_contrast-standard",
&indexer));
Ниже приведено объяснение аргументов, передаваемых в MrmCreateResourceIndexer.
- Имя семейства пакетов целевого приложения UWP, которое будет использоваться в качестве имени карты ресурсов при последующем создании файла PRI из этого индексатора ресурсов.
- Корневой каталог проекта целевого приложения UWP. Другими словами, путь к файлам ресурсов. Мы указываем это, чтобы затем можно было указать пути относительно этого корня в последующих вызовах API к тому же индексатору ресурсов.
- Целевая версия Windows.
- Список квалификаторов ресурсов по умолчанию.
- Указатель на дескриптор индексатора ресурсов, чтобы она была настроена.
Следующим шагом является добавление ресурсов в только что созданный индексатор ресурсов. resources.resw
— это файл ресурсов (RESW), содержащий нейтральные строки для целевого приложения UWP. Прокрутите страницу вверх (в этом разделе), если хотите просмотреть его содержимое. de-DE\resources.resw
содержит наши немецкие строки и en-US\resources.resw
наши английские строки. Чтобы добавить строковые ресурсы в файл ресурсов в индексатор ресурсов, вызовите mrmIndexResourceContainerAutoQualifiers. В-третьих, мы вызываем функцию MrmIndexFile в файл, содержащий нейтральный ресурс изображения индексатору ресурсов.
::ThrowIfFailed(::MrmIndexResourceContainerAutoQualifiers(indexer, L"resources.resw"));
::ThrowIfFailed(::MrmIndexResourceContainerAutoQualifiers(indexer, L"de-DE\\resources.resw"));
::ThrowIfFailed(::MrmIndexResourceContainerAutoQualifiers(indexer, L"en-US\\resources.resw"));
::ThrowIfFailed(::MrmIndexFile(indexer, L"ms-resource:///Files/sample-image.png", L"sample-image.png", L""));
В вызове MrmIndexFile значение L"ms-resource:///Files/sample-image.png" — это универсальный код ресурса ресурса. Первый сегмент пути — "Файлы", и это то, что будет использоваться в качестве имени поддерев карты ресурсов при последующем создании файла PRI из этого индексатора ресурсов.
Познакомившись с индексатором ресурсов о файлах ресурсов, пришло время создать файл PRI на диске, вызвав функцию MrmCreateResourceFile.
::ThrowIfFailed(::MrmCreateResourceFile(indexer, MrmPackagingModeStandaloneFile, MrmPackagingOptionsNone, generatedPRIsFolder.c_str()));
На этом этапе в папке с именем resources.pri
Generated PRIs
PRI-файл был создан. Теперь, когда мы закончим с индексатором ресурсов, мы называем mrmDedexerIndexerAndMessages , чтобы уничтожить его дескриптор и освободить все выделенные им ресурсы компьютера.
::ThrowIfFailed(::MrmDestroyIndexerAndMessages(indexer));
Так как файл PRI является двоичным, это будет проще просматривать то, что мы только что создали, если мы дампам двоичный ФАЙЛ PRI в его XML-эквивалент. Вызов mrmDumpPriFile делает это.
::ThrowIfFailed(::MrmDumpPriFile(filePathPRI.c_str(), nullptr, MrmDumpType::MrmDumpType_Basic, filePathPRIDumpBasic.c_str()));
Ниже приведено объяснение аргументов, передаваемых в MrmDumpPriFile.
- Путь к файлу PRI для дампа. Мы не используем индексатор ресурсов в этом вызове (мы просто уничтожили его), поэтому нам нужно указать полный путь к файлу.
- Файл схемы отсутствует. Рассмотрим схему далее в этом разделе.
- Просто основные сведения.
- Путь к создаваемому XML-файлу.
Это то, что PRI-файл, дампаемый в XML здесь, содержит.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PriInfo>
<ResourceMap name="OurUWPApp" version="1.0" primary="true">
<Qualifiers>
<Language>en-US,de-DE</Language>
</Qualifiers>
<ResourceMapSubtree name="Files">
<NamedResource name="sample-image.png" uri="ms-resource://OurUWPApp/Files/sample-image.png">
<Candidate type="Path">
<Value>sample-image.png</Value>
</Candidate>
</NamedResource>
</ResourceMapSubtree>
<ResourceMapSubtree name="resources">
<NamedResource name="EnOnlyString" uri="ms-resource://OurUWPApp/resources/EnOnlyString">
<Candidate qualifiers="Language-en-US" isDefault="true" type="String">
<Value>EnOnlyString-en-US</Value>
</Candidate>
</NamedResource>
<NamedResource name="LocalizedString1" uri="ms-resource://OurUWPApp/resources/LocalizedString1">
<Candidate qualifiers="Language-en-US" isDefault="true" type="String">
<Value>LocalizedString1-en-US</Value>
</Candidate>
<Candidate type="String">
<Value>LocalizedString1-neutral</Value>
</Candidate>
</NamedResource>
<NamedResource name="LocalizedString2" uri="ms-resource://OurUWPApp/resources/LocalizedString2">
<Candidate qualifiers="Language-de-DE" type="String">
<Value>LocalizedString2-de-DE</Value>
</Candidate>
<Candidate type="String">
<Value>LocalizedString2-neutral</Value>
</Candidate>
</NamedResource>
<NamedResource name="NeutralOnlyString" uri="ms-resource://OurUWPApp/resources/NeutralOnlyString">
<Candidate type="String">
<Value>NeutralOnlyString-neutral</Value>
</Candidate>
</NamedResource>
</ResourceMapSubtree>
</ResourceMap>
</PriInfo>
Информация начинается с карты ресурсов, которая называется с именем семейства пакетов нашего целевого приложения UWP. Заключимые картой ресурсов являются двумя поддеревами карты ресурсов: одна для файловых ресурсов, индексированных и другая для строковых ресурсов. Обратите внимание, что имя семейства пакетов вставляется во все URI ресурсов.
Первый строковый ресурс — EnOnlyString из en-US\resources.resw
, и он имеет только одного кандидата (который соответствует квалификатору language-en-US ). Далее происходит LocalizedString1 из обоих resources.resw
и en-US\resources.resw
. Следовательно, он имеет двух кандидатов: один соответствующий язык-en-US, и резервный нейтральный кандидат, который соответствует любому контексту. Аналогичным образом LocalizedString2 имеет двух кандидатов: language-de-DE и нейтральных. И, наконец, NeutralOnlyString существует только в нейтральной форме. Я дал ему это имя, чтобы ясно, что он не предназначен для локализации.
Итоги
В этом сценарии мы показали, как использовать API индексирования ресурсов пакета (PRI) для создания индексатора ресурсов. Мы добавили строковые ресурсы и файлы ресурсов в индексатор ресурсов. Затем мы использовали индексатор ресурсов для создания двоичного файла PRI. Наконец, мы дампы двоичного файла PRI в виде XML, чтобы убедиться, что он содержит ожидаемые сведения.