Bagikan melalui


Skenario 1: Menghasilkan file PRI dari sumber daya string dan file aset

Dalam skenario ini, kita akan menggunakan API pengindeksan sumber daya paket (PRI) untuk membuat aplikasi baru untuk mewakili sistem build kustom kita. Tujuan dari sistem build kustom ini, ingat, adalah untuk membuat file PRI untuk aplikasi UWP target. Jadi, sebagai bagian dari panduan ini, kita akan membuat beberapa file sumber daya sampel (berisi string, dan jenis sumber daya lainnya) untuk mewakili sumber daya aplikasi UWP target tersebut.

Proyek baru

Mulailah dengan membuat proyek baru di Microsoft Visual Studio. Buat proyek Aplikasi Konsol Windows Visual C++, dan beri nama CBSConsoleApp (untuk "aplikasi konsol sistem build kustom").

Pilih x64 dari menu drop-down Platform Solusi.

Header, pustaka statis, dan dll

API PRI dideklarasikan dalam file header MrmResourceIndexer.h (yang diinstal ke %ProgramFiles(x86)%\Windows Kits\10\Include\<WindowsTargetPlatformVersion>\um\). Buka file CBSConsoleApp.cpp dan sertakan header bersama dengan beberapa header lain yang akan Anda butuhkan.

#include <string>
#include <windows.h>
#include <MrmResourceIndexer.h>

API diimplementasikan dalam MrmSupport.dll, yang Anda akses dengan menautkan ke pustaka statis MrmSupport.lib. Buka Properti proyek Anda, klik Input Linker>, edit AdditionalDependencies dan tambahkan .MrmSupport.lib

Bangun Solusi, lalu salin MrmSupport.dll dari C:\Program Files (x86)\Windows Kits\10\bin\<WindowsTargetPlatformVersion>\x64\ ke folder output build Anda (mungkin C:\Users\%USERNAME%\source\repos\CBSConsoleApp\x64\Debug\).

Tambahkan fungsi pembantu berikut ke CBSConsoleApp.cpp, karena kita akan membutuhkannya.

inline void ThrowIfFailed(HRESULT hr)
{
	if (FAILED(hr))
	{
		// Set a breakpoint on this line to catch Win32 API errors.
		throw new std::exception();
	}
}

main() Dalam fungsi , tambahkan panggilan untuk menginisialisasi dan membatalkan inisialisasi COM.

int main()
{
	::ThrowIfFailed(::CoInitializeEx(nullptr, COINIT_MULTITHREADED));
	
	// More code will go here.
	
	::CoUninitialize();
}

File sumber daya milik aplikasi UWP target

Sekarang kita akan memerlukan beberapa file sumber daya sampel (berisi string, dan jenis sumber daya lainnya) untuk mewakili sumber daya aplikasi UWP target. Ini, tentu saja, dapat ditemukan di mana saja di sistem file Anda. Tetapi untuk panduan ini, akan lebih mudah untuk menempatkannya di folder proyek CBSConsoleApp sehingga semuanya berada di satu tempat. Anda hanya perlu menambahkan file sumber daya ini ke sistem file; jangan tambahkan ke proyek CBSConsoleApp.

Di dalam folder yang sama yang berisi CBSConsoleApp.vcxproj, tambahkan subfolder baru bernama UWPAppProjectRootFolder. Di dalam subfolder baru tersebut, buat file sumber daya sampel ini.

\UWPAppProjectRootFolder\sample-image.png

File ini dapat berisi gambar PNG apa pun.

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

Indeks sumber daya, dan buat file PRI

main() Dalam fungsi , sebelum panggilan untuk menginisialisasi COM, nyatakan beberapa string yang akan kita butuhkan, dan juga membuat folder output tempat kita akan menghasilkan file PRI kita.

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

Segera setelah panggilan untuk Menginisialisasi COM, nyatakan handel pengindeks sumber daya lalu panggil MrmCreateResourceIndexer untuk membuat pengindeks sumber daya.

MrmResourceIndexerHandle indexer;
::ThrowIfFailed(::MrmCreateResourceIndexer(
	L"OurUWPApp",
	projectRootFolderUWPApp.c_str(),
	MrmPlatformVersion::MrmPlatformVersion_Windows10_0_0_0,
	L"language-en_scale-100_contrast-standard",
	&indexer));

Berikut adalah penjelasan tentang argumen yang diteruskan ke MrmCreateResourceIndexer.

  • Nama keluarga paket dari aplikasi UWP target kami, yang akan digunakan sebagai nama peta sumber daya ketika kita kemudian membuat file PRI dari pengindeks sumber daya ini.
  • Akar proyek dari aplikasi UWP target kami. Dengan kata lain, jalur ke file sumber daya kami. Kami menentukan ini sehingga kami kemudian dapat menentukan jalur yang relatif terhadap akar tersebut dalam panggilan API berikutnya ke pengindeks sumber daya yang sama.
  • Versi Windows yang ingin kita targetkan.
  • Daftar kualifikasi sumber daya default.
  • Penunjuk ke handel pengindeks sumber daya kami sehingga fungsi dapat mengaturnya.

Langkah selanjutnya adalah menambahkan sumber daya kami ke pengindeks sumber daya yang baru saja kami buat. resources.resw adalah File Sumber Daya (.resw) yang berisi string netral untuk aplikasi UWP target kami. Gulir ke atas (dalam topik ini) jika Anda ingin melihat isinya. de-DE\resources.resw berisi string Jerman kami, dan en-US\resources.resw string bahasa Inggris kami. Untuk menambahkan sumber daya string di dalam File Sumber Daya ke pengindeks sumber daya, Anda memanggil MrmIndexResourceContainerAutoQualifiers. Ketiga, kami memanggil fungsi MrmIndexFile ke file yang berisi sumber daya gambar netral ke pengindeks sumber daya.

::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""));

Dalam panggilan ke MrmIndexFile, nilai L"ms-resource:///Files/sample-image.png" adalah uri sumber daya. Segmen jalur pertama adalah "Files", dan itulah yang akan digunakan sebagai nama subtree peta sumber daya ketika kita kemudian menghasilkan file PRI dari pengindeks sumber daya ini.

Setelah memberi tahu pengindeks sumber daya tentang file sumber daya kami, saatnya untuk membuat file PRI pada disk dengan memanggil fungsi MrmCreateResourceFile.

::ThrowIfFailed(::MrmCreateResourceFile(indexer, MrmPackagingModeStandaloneFile, MrmPackagingOptionsNone, generatedPRIsFolder.c_str()));

Pada titik ini, file PRI bernama resources.pri telah dibuat di dalam folder bernama Generated PRIs. Setelah selesai dengan pengindeks sumber daya, kami memanggil MrmDestroyIndexerAndMessages untuk menghancurkan handelnya dan merilis sumber daya mesin apa pun yang dialokasikannya.

::ThrowIfFailed(::MrmDestroyIndexerAndMessages(indexer));

Karena file PRI adalah biner, akan lebih mudah untuk melihat apa yang baru saja kita hasilkan jika kita membuang file PRI biner ke XML-nya yang setara. Panggilan ke MrmDumpPriFile melakukan hal itu.

::ThrowIfFailed(::MrmDumpPriFile(filePathPRI.c_str(), nullptr, MrmDumpType::MrmDumpType_Basic, filePathPRIDumpBasic.c_str()));

Berikut adalah penjelasan tentang argumen yang diteruskan ke MrmDumpPriFile.

  • Jalur ke file PRI untuk dibuang. Kami tidak menggunakan pengindeks sumber daya dalam panggilan ini (kami baru saja menghancurkannya), jadi kami perlu menentukan jalur file lengkap.
  • Tidak ada file skema. Kita akan membahas apa itu skema nanti dalam topik.
  • Hanya info dasar.
  • Jalur file XML yang akan dibuat.

Inilah yang dimuat file PRI, yang dicadangkan ke XML di sini.

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

Info dimulai dengan peta sumber daya, yang dinamai dengan nama keluarga paket aplikasi UWP target kami. Diapit oleh peta sumber daya adalah dua subtree peta sumber daya: satu untuk sumber daya file yang kami indeks, dan satu lagi untuk sumber daya string kami. Perhatikan bagaimana nama keluarga paket telah dimasukkan ke dalam semua URI sumber daya.

Sumber daya string pertama adalah EnOnlyString dari en-US\resources.resw, dan hanya memiliki satu kandidat (yang cocok dengan kualifikasi bahasa-en-AS ). Selanjutnya datang LocalizedString1 dari dan resources.reswen-US\resources.resw. Akibatnya, ia memiliki dua kandidat: satu bahasa-en-AS yang cocok, dan kandidat netral fallback yang cocok dengan konteks apa pun. Demikian pula, LocalizedString2 memiliki dua kandidat: language-de-DE, dan netral. Dan, akhirnya, NeutralOnlyString hanya ada dalam bentuk netral. Aku memberinya nama itu untuk memperjelas bahwa itu tidak dimaksudkan untuk dilokalkan.

Ringkasan

Dalam skenario ini, kami menunjukkan cara menggunakan API pengindeksan sumber daya paket (PRI) untuk membuat pengindeks sumber daya. Kami menambahkan sumber daya string dan file aset ke pengindeks sumber daya. Kemudian, kami menggunakan pengindeks sumber daya untuk menghasilkan file PRI biner. Dan akhirnya kami membuang file PRI biner dalam bentuk XML sehingga kami dapat mengonfirmasi bahwa file tersebut berisi info yang kami harapkan.

API penting