案例 1:從字串資源和資產檔案產生 PRI 檔案
在此案例中,我們將使用套件資源索引 (PRI) API 來建立新的應用程式來代表我們的自訂建置系統。 請記住,此自訂建置系統的目的是為目標 UWP 應用程式建立 PRI 檔案。 因此,在此逐步解說中,我們將建立一些範例資源檔 (包含字串和其他種類的資源_,以代表該目標 UWP 應用程式的資源。
新增專案
請先在 Microsoft Visual Studio 中,建立新的專案。 建立一個 Visual C++ Windows 主控台應用程式專案,並將其命名為 CBSConsoleApp (針對「自訂建置系統主控台應用程式」)。
從 解決方案平台下拉式清單中選擇 x64。
標題、靜態程式庫和 dll
PRI API 在 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 來存取。 開啟專案的 屬性,按一下 Linker>Input,編輯AdditionalDependencies,並新增 MrmSupport.lib
。
建置解決方案,然後複製 MrmSupport.dll
到 C:\Program Files (x86)\Windows Kits\10\bin\<WindowsTargetPlatformVersion>\x64\
建置輸出資料夾 (可能是 C:\Users\%USERNAME%\source\repos\CBSConsoleApp\x64\Debug\
)。
將以下 Helper 函數新增到 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);
呼叫 Initialize 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" 是資源 uri。 第一個路徑區段是「檔案」,當我們稍後從此資源索引子產生 PRI 檔案時,會用做為資源地圖樹狀子目錄名稱。
在向資源索引子簡要介紹了我們的資源檔案後,是時候讓它透過呼叫 MrmCreateResourceFile 函數在磁碟上產生一個 PRI 檔案。
::ThrowIfFailed(::MrmCreateResourceFile(indexer, MrmPackagingModeStandaloneFile, MrmPackagingOptionsNone, generatedPRIsFolder.c_str()));
此時,在名為 Generated PRIs
的資料夾內已建立了名為 resources.pri
的 PRI 檔案。 現在我們已經完成了資源索引子,我們呼叫 MrmDestroyIndexerAndMessages 來銷毀它的常式並釋放它所指派的任何機器資源。
::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 中。
第一個字串資源是來自 en-US\resources.resw
的 EnOnlyString,它只有一個候選項目 (與 language-en-US 限定符相符)。 接下來是來自 resources.resw
和 en-US\resources.resw
的 LocalizedString1。 因此,它有兩個候選項目:一個符合 language-en-US,另一個符合任何內容的後備中性候選項目。 同樣地,LocalizedString2 有兩個候選項目:language-de-DE 和中性。 最後,NeutralOnlyString 只以中性形式存在。 我給它起這個名字是為了表明它不適合當地語系化。
摘要
在此案例中,我們示範如何使用套件資源索引 (PRI) API 建立資源索引子。 我們已將字串資源和資產檔案新增至資源索引子。 然後,我們使用資源索引器匯出了一個二進制 PRI 文件。 最後,我們會以 XML 形式傾印二進位 PRI 檔案,以便我們可以確認它包含預期的資訊。