Het Windows 10 Resource Management System gebruiken in een verouderde app of game

.NET- en Win32-apps en -games worden vaak gelokaliseerd in verschillende talen om hun totale adresseerbare markt uit te breiden. Zie Globalization and localizationvoor meer informatie over de waardepropositie van het lokaliseren van uw app. Door uw .NET- of Win32-app of -game te verpakken als een MSIX- of .appx-pakket, kunt u gebruikmaken van het Resource Management-systeem om app-resources te laden die zijn afgestemd op de runtimecontext. In dit uitgebreide onderwerp worden de technieken beschreven.

Er zijn veel manieren om een traditionele Win32-toepassing te lokaliseren, maar Windows 8 heeft een nieuw systeem voor resourcebeheer geïntroduceerd dat in programmeertalen, in verschillende toepassingstypen werkt en functionaliteit biedt boven en boven eenvoudige lokalisatie. Dit systeem wordt in dit onderwerp aangeduid als 'MRT'. Historisch gezien stond dat voor "Moderne hulpbrontechnologie", maar de term "Modern" wordt niet meer gebruikt. De resourcemanager kan ook wel MRM (Modern Resource Manager) of PRI (Package Resource Index) worden genoemd.

In combinatie met implementatie op basis van MSIX of .appx (bijvoorbeeld uit de Microsoft Store), kan MRT automatisch de meest toepasselijke resources leveren voor een bepaalde gebruiker/apparaat, waardoor de download- en installatiegrootte van uw toepassing wordt geminimaliseerd. Deze groottevermindering kan aanzienlijk zijn voor toepassingen met een grote hoeveelheid gelokaliseerde inhoud, mogelijk op volgorde van meerdere gigabytes voor AAA-games. Extra voordelen van MRT zijn gelokaliseerde vermeldingen in de Windows Shell en de Microsoft Store, automatische terugvallogica wanneer de voorkeurstaal van een gebruiker niet overeenkomt met uw beschikbare resources.

In dit document wordt de architectuur op hoog niveau van MRT beschreven en vindt u een handleiding voor het overzetten van verouderde Win32-toepassingen naar MRT met minimale codewijzigingen. Zodra de overstap naar MRT is gemaakt, zijn er extra voordelen (zoals de mogelijkheid om resources te segmenteren op schaalfactor of systeemthema) beschikbaar voor de ontwikkelaar. Let op: lokalisatie op basis van MRT werkt voor zowel UWP-toepassingen als Win32-toepassingen die worden verwerkt door de Desktop Bridge (ook wel Centennial genoemd).

In veel situaties kunt u uw bestaande lokalisatie-indelingen en broncode blijven gebruiken terwijl u integreert met MRT voor het oplossen van resources tijdens runtime en het minimaliseren van downloadgrootten. Dit is geen alles-of-niets-benadering. De volgende tabel bevat een overzicht van het werk en de geschatte kosten/baten van elke fase. Deze tabel bevat geen niet-lokalisatietaken, zoals het leveren van toepassingspictogrammen met hoge resolutie of hoog contrast. Voor meer informatie over het bieden van meerdere assets voor tegels, pictogrammen, enzovoort, zie Uw resources aanpassen voor taal, schaal, hoog contrast en andere criteria.

Werk Voordeel Geschatte kosten
Pakketmanifest lokaliseren Minimaal werk dat vereist is om uw gelokaliseerde inhoud weer te geven in de Windows Shell en in de Microsoft Store Klein
MRT gebruiken om resources te identificeren en te zoeken Vereisten voor het minimaliseren van download- en installatiegrootten; automatische taalterugval Gemiddeld
Resourcepacks bouwen Laatste stap om download- en installatiegrootten te minimaliseren Klein
Migreren naar MRT-resourceindelingen en API's Aanzienlijk kleinere bestandsgrootten (afhankelijk van bestaande resourcetechnologie) Groot

Introductie

De meeste niet-triviale toepassingen bevatten elementen van de gebruikersinterface die bekend staan als resources die losgekoppeld zijn van de code van de toepassing (in tegenstelling tot in code vastgelegde waarden die zijn geschreven in de broncode zelf). Er zijn verschillende redenen om de voorkeur te geven aan resources ten opzichte van in code vastgelegde waarden, bijvoorbeeld eenvoudig te bewerken door niet-ontwikkelaars, maar een van de belangrijkste redenen is om de toepassing in staat te stellen verschillende weergaven van dezelfde logische resource tijdens runtime te kiezen. De tekst die moet worden weergegeven op een knop (of de afbeelding die in een pictogram moet worden weergegeven) kan bijvoorbeeld verschillen, afhankelijk van de taal(en) die de gebruiker begrijpt, de kenmerken van het weergaveapparaat of of de gebruiker ondersteunende technologieën heeft ingeschakeld.

Het primaire doel van elke technologie voor resourcebeheer is dus om tijdens runtime een aanvraag voor een logische of symbolische resourcenaam (zoals SAVE_BUTTON_LABEL) te vertalen naar de best mogelijke werkelijke waarde (bijvoorbeeld 'Opslaan') uit een set mogelijke kandidaten (bijvoorbeeld "Opslaan", "Speichern" of "저장"). MRT biedt een dergelijke functie en stelt toepassingen in staat om resourcekandidaten te identificeren met behulp van een groot aantal kenmerken, kwalificatiesgenoemd, zoals de taal van de gebruiker, de weergaveschaalfactor, het geselecteerde thema van de gebruiker en andere omgevingsfactoren. MRT ondersteunt zelfs aangepaste kwalificatieprogramma's voor toepassingen die dit nodig hebben (een toepassing kan bijvoorbeeld verschillende grafische assets bieden voor gebruikers die zijn aangemeld met een account versus gastgebruikers, zonder deze controle expliciet toe te voegen aan elk deel van hun toepassing). MRT werkt met zowel tekenreeksbronnen als bestandsbronnen, waarbij bestandsbronnen worden geïmplementeerd als verwijzingen naar de externe gegevens (de bestanden zelf).

Voorbeeld

Hier volgt een eenvoudig voorbeeld van een toepassing met tekstlabels op twee knoppen (openButton en saveButton) en een PNG-bestand dat wordt gebruikt voor een logo (logoImage). De tekstlabels worden gelokaliseerd in het Engels en Duits en het logo is geoptimaliseerd voor normale bureaubladweergaven (100% schaalfactor) en telefoons met een hoge resolutie (300% schaalfactor). Houd er rekening mee dat dit diagram een conceptueel overzicht van hoog niveau van het model weergeeft; het komt niet precies overeen met de implementatie.

schermopname van een broncodelabel, een opzoektabellabel en een label bestanden op schijf.

In de afbeelding verwijst de toepassingscode naar de drie namen van logische resources. Tijdens runtime gebruikt de GetResource pseudofunctie MRT om deze resourcenamen in de resourcetabel (bekend als PRI-bestand) te zoeken en de meest geschikte kandidaat te vinden op basis van de omgevingsomstandigheden (de taal van de gebruiker en de schaalfactor van de weergave). In het geval van de labels worden de tekenreeksen rechtstreeks gebruikt. In het geval van de logoafbeelding worden de tekenreeksen geïnterpreteerd als bestandsnamen en worden de bestanden van de schijf gelezen.

Als de gebruiker een andere taal dan Engels of Duits spreekt of een andere weergaveschaalfactor heeft dan 100% of 300%, kiest MRT de 'dichtstbijzijnde' overeenkomende kandidaat op basis van een set terugvalregels (zie Resource Management System voor meer achtergrond).

MRT ondersteunt resources die zijn afgestemd op meer dan één kwalificatie. Bijvoorbeeld, als de logoafbeelding ingebedde tekst bevat die ook moet worden gelokaliseerd, dan heeft het logo vier kandidaten: EN/Scale-100, DE/Scale-100, EN/Scale-300 en DE/Scale-300.

Paragrafen in dit document

In de volgende secties worden de taken op hoog niveau beschreven die nodig zijn om MRT te integreren met uw toepassing.

Fase 0: Een toepassingspakket bouwen

Deze sectie omschrijft hoe u uw huidige bureaubladtoepassing kunt omzetten naar een toepassingspakket. Er worden in deze fase geen MRT-functies gebruikt.

Fase 1: Het toepassingsmanifest lokaliseren

In deze sectie wordt beschreven hoe u het manifest van uw toepassing kunt lokaliseren (zodat dit correct wordt weergegeven in de Windows Shell) terwijl u de verouderde resourceindeling en API nog steeds gebruikt om resources te verpakken en te zoeken.

Fase 2: MRT gebruiken om resources te identificeren en te vinden

In deze sectie wordt beschreven hoe u uw toepassingscode (en mogelijk de indeling van resources) kunt wijzigen om resources te vinden met mrt, terwijl u nog steeds uw bestaande resourceindelingen en API's gebruikt om de resources te laden en te gebruiken.

Fase 3: Resourcepacks bouwen

In deze sectie worden de laatste wijzigingen beschreven die nodig zijn om uw resources te scheiden in afzonderlijke resourcepakketten, waardoor de downloadgrootte (en installatie) van uw app wordt geminimaliseerd.

Niet behandeld in dit document

Nadat fase 0-3 hierboven is voltooid, hebt u een toepassing 'bundel' die kan worden ingediend bij de Microsoft Store en waarmee de download- en installatiegrootte voor gebruikers wordt geminimaliseerd door de resources weg te laten die ze niet nodig hebben (bijvoorbeeld talen die ze niet spreken). Verdere verbeteringen in de grootte en functionaliteit van toepassingen kunnen worden aangebracht door één laatste stap uit te voeren.

Fase 4: Migreren naar MRT-resourceindelingen en API's

Deze fase valt buiten het bereik van dit document; het omvat het verplaatsen van uw resources (met name tekenreeksen) van verouderde formaten, zoals MUI-DLL's of .NET-resourceassemblies, naar PRI-bestanden. Dit kan leiden tot verdere ruimtebesparing voor download- en installatiegrootten. Het maakt ook het gebruik van andere MRT-functies mogelijk, zoals het minimaliseren van het downloaden en installeren van afbeeldingsbestanden op basis van schaalfactor, toegankelijkheidsinstellingen, enzovoort.

Fase 0: Een toepassingspakket bouwen

Voordat u wijzigingen aanbrengt in de resources van uw toepassing, moet u eerst uw huidige verpakkings- en installatietechnologie vervangen door de standaard UWP-verpakkings- en implementatietechnologie. U kunt dit op drie manieren doen:

  • Als u een grote bureaubladtoepassing hebt met een complex installatieprogramma of als u veel uitbreidbaarheidspunten van het besturingssysteem gebruikt, kunt u het hulpprogramma Desktop App Converter gebruiken om de INDELING van uw UWP-bestand en manifestgegevens van uw bestaande app-installatieprogramma te genereren (bijvoorbeeld een MSI).
  • Als u een kleinere bureaubladtoepassing hebt met relatief weinig bestanden of een eenvoudig installatieprogramma en geen uitbreidbaarheidshaken, kunt u de bestandsindeling en manifestgegevens handmatig maken.
  • Als u opnieuw bouwt vanaf de bron en uw app wilt bijwerken als een pure UWP-toepassing, kunt u een nieuw project maken in Visual Studio en vertrouwen op de IDE om veel van het werk voor u uit te voeren.

Als u het Desktop App Converter-wilt gebruiken, raadpleegt u Een bureaubladtoepassing verpakken met behulp van het desktop-app-conversieprogramma voor meer informatie over het conversieproces. Een volledige set Desktop Converter-voorbeelden vindt u op de Desktop Bridge naar UWP-voorbeelden gitHub-opslagplaats.

Opmerking

Het Desktop App Converter is verouderd verklaard. Gebruik het nieuwe en verbeterde MSIX Packaging Tool om uw bureaublad-apps te verpakken.

Als u het pakket handmatig wilt maken, moet u een mapstructuur maken die alle bestanden van uw toepassing bevat (uitvoerbare bestanden en inhoud, maar niet broncode) en een pakketmanifestbestand (.appxmanifest). Een voorbeeld is te vinden in het Hello, World GitHub-voorbeeld, maar een basispakketmanifestbestand dat het bureaubladprogramma met de naam ContosoDemo.exe uitvoert, is als volgt, waarbij de gemarkeerde tekst wordt vervangen door uw eigen waarden.

<?xml version="1.0" encoding="utf-8" ?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
         xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
         xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
         xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
         IgnorableNamespaces="uap mp rescap">
    <Identity Name="Contoso.Demo"
              Publisher="CN=Contoso.Demo"
              Version="1.0.0.0" />
    <Properties>
    <DisplayName>Contoso App</DisplayName>
    <PublisherDisplayName>Contoso, Inc</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>
    <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" 
                        MaxVersionTested="10.0.14393.0" />
  </Dependencies>
    <Resources>
    <Resource Language="en-US" />
  </Resources>
    <Applications>
    <Application Id="ContosoDemo" Executable="ContosoDemo.exe" 
                 EntryPoint="Windows.FullTrustApplication">
    <uap:VisualElements DisplayName="Contoso Demo" BackgroundColor="#777777" 
                        Square150x150Logo="Assets\Square150x150Logo.png" 
                        Square44x44Logo="Assets\Square44x44Logo.png" 
        Description="Contoso Demo">
      </uap:VisualElements>
    </Application>
  </Applications>
    <Capabilities>
    <rescap:Capability Name="runFullTrust" />
  </Capabilities>
</Package>

Zie App-pakketmanifestvoor meer informatie over het pakketmanifestbestand en de pakketindeling.

Als u Visual Studio gebruikt om een nieuw project te maken en uw bestaande code over te brengen, raadpleegt u Een 'Hallo wereld'-app maken. U kunt uw bestaande code opnemen in het nieuwe project, maar waarschijnlijk moet u belangrijke codewijzigingen aanbrengen (met name in de gebruikersinterface) om te worden uitgevoerd als een pure UWP-app. Deze wijzigingen vallen buiten het bereik van dit document.

Fase 1: Het manifest lokaliseren

Stap 1.1: Tekenreeksen en assets bijwerken in het manifest

In fase 0 hebt u een basispakketmanifestbestand (.appxmanifest) gemaakt voor uw toepassing (op basis van de waarden die zijn opgegeven voor het conversieprogramma, geëxtraheerd uit het MSI- of handmatig ingevoerd in het manifest), maar bevat deze geen gelokaliseerde informatie, noch biedt het ondersteuning voor aanvullende functies zoals tegelassets met een hoge resolutie, enzovoort.

Om ervoor te zorgen dat de naam en beschrijving van uw toepassing correct zijn gelokaliseerd, moet u bepaalde resources in een set resourcebestanden definiëren en het pakketmanifest bijwerken om ernaar te verwijzen.

Een standaardresourcebestand maken

De eerste stap is het maken van een standaardresourcebestand in uw standaardtaal (bijvoorbeeld Amerikaans Engels). U kunt dit handmatig doen met een teksteditor of via Resource Designer in Visual Studio.

Als u de resources handmatig wilt maken:

  1. Maak een XML-bestand met de naam resources.resw en plaats het in een Strings\en-us submap van uw project. Gebruik de juiste BCP-47-code als uw standaardtaal geen Amerikaans Engels is.
  2. Voeg in het XML-bestand de volgende inhoud toe, waarbij de gemarkeerde tekst wordt vervangen door de juiste tekst voor uw app, in uw standaardtaal.

Opmerking

Er gelden beperkingen voor de lengte van sommige van deze tekenreeksen. Zie VisualElementsvoor meer informatie.

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="ApplicationDescription">
    <value>Contoso Demo app with localized resources (English)</value>
  </data>
  <data name="ApplicationDisplayName">
    <value>Contoso Demo Sample (English)</value>
  </data>
  <data name="PackageDisplayName">
    <value>Contoso Demo Package (English)</value>
  </data>
  <data name="PublisherDisplayName">
    <value>Contoso Samples, USA</value>
  </data>
  <data name="TileShortName">
    <value>Contoso (EN)</value>
  </data>
</root>

Als u de ontwerpfunctie in Visual Studio wilt gebruiken:

  1. Maak de Strings\en-us map (of een andere taal indien van toepassing) in uw project en voeg een Nieuw item toe aan de hoofdmap van uw project, met behulp van de standaardnaam van resources.resw. Zorg ervoor dat u resourcesbestand (.resw) kiest en niet resourcewoordenlijst. Een resourcewoordenlijst is een bestand dat wordt gebruikt door XAML-toepassingen.
  2. Voer met behulp van de ontwerpfunctie de volgende tekenreeksen in (gebruik dezelfde Names maar vervang de Values door de juiste tekst voor uw toepassing):

Schermopname van het bestand Resources.resw met de kolommen Naam en Waarde. voor de resources.

Opmerking

Als u begint met de Visual Studio-ontwerpfunctie, kunt u de XML altijd rechtstreeks bewerken door op F7te drukken. Maar als u begint met een minimaal XML-bestand, herkent de ontwerper het bestand niet omdat er veel extra metagegevens ontbreken; U kunt dit oplossen door de XSD-gegevens van een door de ontwerper gegenereerd bestand naar uw met de hand bewerkte XML-bestand te kopiëren.

Het manifest bijwerken om te verwijzen naar de resources

Nadat u de waarden hebt gedefinieerd in het bestand .resw, moet u het manifest bijwerken om te verwijzen naar de resourcereeksen. Ook hier kunt u een XML-bestand rechtstreeks bewerken of afhankelijk zijn van de Visual Studio Manifest Designer.

Als u XML rechtstreeks bewerkt, opent u het AppxManifest.xml bestand en voert u de volgende wijzigingen aan in de gemarkeerde waarden. Gebruik deze exacte tekst, niet specifiek voor uw toepassing. U hoeft deze exacte resourcenamen niet te gebruiken, maar u kunt zelf kiezen, maar wat u ook kiest, moet exact overeenkomen met wat er in het .resw bestand staat. Deze namen moeten overeenkomen met de Names die u in het .resw-bestand hebt gemaakt, voorafgegaan door het ms-resource:-schema en de Resources/-naamruimte.

Opmerking

Veel elementen van het manifest zijn weggelaten uit dit fragment - verwijder niets!

<?xml version="1.0" encoding="utf-8"?>
<Package>
  <Properties>
    <DisplayName>ms-resource:Resources/PackageDisplayName</DisplayName>
    <PublisherDisplayName>ms-resource:Resources/PublisherDisplayName</PublisherDisplayName>
  </Properties>
  <Applications>
    <Application>
      <uap:VisualElements DisplayName="ms-resource:Resources/ApplicationDisplayName"
        Description="ms-resource:Resources/ApplicationDescription">
        <uap:DefaultTile ShortName="ms-resource:Resources/TileShortName">
          <uap:ShowNameOnTiles>
            <uap:ShowOn Tile="square150x150Logo" />
          </uap:ShowNameOnTiles>
        </uap:DefaultTile>
      </uap:VisualElements>
    </Application>
  </Applications>
</Package>

Als u de visual Studio-manifestontwerper gebruikt, opent u het .appxmanifest-bestand en wijzigt u de gemarkeerde waarden waarden op het tabblad *Application en het tabblad Packaging:

Schermopname van Visual Studio Manifest Designer met het tabblad Toepassing met de tekstvakken Weergavenaam en Beschrijving gemarkeerd.

Schermopname van Visual Studio Manifest Designer met het tabblad Verpakking met de tekstvakken Pakketweergave en Publisher-weergavenaam gemarkeerd.

Stap 1.2: EEN PRI-bestand bouwen, een MSIX-pakket maken en controleren of het werkt

U moet nu het .pri-bestand kunnen bouwen en de toepassing implementeren om te controleren of de juiste informatie (in uw standaardtaal) wordt weergegeven in het menu Start.

Als u in Visual Studio bouwt, drukt u op Ctrl+Shift+B om het project te bouwen en klikt u met de rechtermuisknop op het project en kiest u Deploy in het snelmenu.

Als u handmatig bouwt, volgt u deze stappen om een configuratiebestand te maken voor MakePRI hulpprogramma en om het .pri bestand zelf te genereren (meer informatie vindt u in Handmatige app-verpakking):

  1. Open een opdrachtprompt voor ontwikkelaars vanuit de map Visual Studio 2019 of Visual Studio 2022 in het menu Start.

  2. Schakel over naar de hoofdmap van het project (de map die het .appxmanifest-bestand en de Tekenreeksen map bevat).

  3. Typ de volgende opdracht, waarbij u "contoso_demo.xml" vervangt door een naam die geschikt is voor uw project en "en-US" door de standaardtaal van uw app (of zorg ervoor dat deze en-US indien van toepassing). Let op: het XML-bestand wordt gemaakt in de bovenliggende map (niet in de projectmap) omdat het geen deel uitmaakt van de toepassing (u kunt elke andere map kiezen die u wilt gebruiken, maar zorg ervoor dat u dat in toekomstige opdrachten vervangt).

    makepri createconfig /cf ..\contoso_demo.xml /dq en-US /pv 10.0 /o
    

    U kunt makepri createconfig /? typen om te zien wat elke parameter doet, maar in het kort:

    • /cf stelt de bestandsnaam van de configuratie in (de uitvoer van deze opdracht)
    • /dq stelt de standaardkwalificaties in, in dit geval de taal en-US
    • /pv stelt de platformversie in, in dit geval Windows 10
    • /o stelt dit in om het uitvoerbestand te overschrijven als het bestaat
  4. Nu u een configuratiebestand hebt, voert u MakePRI opnieuw uit om daadwerkelijk naar de schijf te zoeken naar resources en deze in een PRI-bestand te verpakken. Vervang "contoso_demop.xml" door de XML-bestandsnaam die u in de vorige stap hebt gebruikt en zorg ervoor dat u de hoofdmap opgeeft voor zowel invoer als uitvoer.

    makepri new /pr . /cf ..\contoso_demo.xml /of ..\resources.pri /mf AppX /o
    

    U kunt makepri new /? typen om te zien wat elke parameter doet, maar in een notendop:

    • /pr stelt de hoofdmap van het project in (in dit geval de huidige map)
    • /cf stelt de configuratiebestandsnaam in, gemaakt in de vorige stap
    • /of het uitvoerbestand instellen
    • /mf maakt een mappingbestand (zodat we bestanden in het pakket in een latere stap kunnen uitsluiten)
    • /o stelt dit in om het uitvoerbestand te overschrijven als het bestaat
  5. U hebt nu een .pri bestand met de standaardtaalresources (bijvoorbeeld en-US). Als u wilt controleren of deze correct werkt, kunt u de volgende opdracht uitvoeren:

    makepri dump /if ..\resources.pri /of ..\resources /o
    

    U kunt makepri dump /? typen om te zien wat elke parameter doet, maar in een notendop:

    • /if stelt de invoerbestandsnaam in
    • /of stelt de uitvoerbestandsnaam in (.xml wordt automatisch toegevoegd)
    • /o stelt dit in om het uitvoerbestand te overschrijven als het bestaat
  6. Ten slotte kunt u ..\resources.xml openen in een teksteditor en controleren of uw <NamedResource> waarden (zoals ApplicationDescription en PublisherDisplayName) worden vermeld, samen met <Candidate> waarden voor de door u gekozen standaardtaal (er is nog andere inhoud aan het begin van het bestand; negeer dat voorlopig).

U kunt het toewijzingsbestand openen ..\resources.map.txt om te controleren of het de bestanden bevat die nodig zijn voor uw project (inclusief het PRI-bestand, dat geen deel uitmaakt van de map van het project). Belangrijk: het toewijzingsbestand niet een verwijzing naar het resources.resw-bestand bevatten omdat de inhoud van dat bestand al is ingesloten in het PRI-bestand. Deze bevat echter andere resources, zoals de bestandsnamen van uw afbeeldingen.

Het pakket bouwen en ondertekenen

Nu het PRI-bestand is gebouwd, kunt u het pakket bouwen en ondertekenen:

  1. Als u het app-pakket wilt maken, voert u de volgende opdracht uit om contoso_demo.appx te vervangen door de naam van het .msix/.appx-bestand dat u wilt maken en ervoor te zorgen dat u een andere map voor het bestand kiest (in dit voorbeeld wordt de bovenliggende map gebruikt; het kan overal zijn, maar moet niet de projectmap zijn).

    makeappx pack /m AppXManifest.xml /f ..\resources.map.txt /p ..\contoso_demo.appx /o
    

    U kunt makeappx pack /? typen om te zien wat elke parameter doet, maar in een notendop:

    • /m stelt het manifestbestand in voor gebruik
    • /f stelt het configuratiebestand in dat moet worden gebruikt (aangemaakt in de vorige stap)
    • /p de naam van het uitvoerpakket instellen
    • /o stelt dit in om het uitvoerbestand te overschrijven als het bestaat
  2. Nadat het pakket is gemaakt, moet het ondertekend worden. De eenvoudigste manier om een handtekeningcertificaat op te halen is door een leeg Universeel Windows-project te maken in Visual Studio en het .pfx bestand te kopiëren dat het maakt, maar u kunt er handmatig een maken met behulp van de MakeCert en Pvk2Pfx hulpprogramma's, zoals beschreven in Een certificaat voor app-pakketondertekening maken.

    Belangrijk

    Als u handmatig een handtekeningcertificaat maakt, moet u ervoor zorgen dat u de bestanden in een andere map plaatst dan uw bronproject of de pakketbron, anders wordt het mogelijk opgenomen als onderdeel van het pakket, inclusief de persoonlijke sleutel.

  3. Gebruik de volgende opdracht om het pakket te ondertekenen. Houd er rekening mee dat de Publisher die is opgegeven in het Identity element van de AppxManifest.xml overeenkomen met de Subject van het certificaat (dit is niet het <PublisherDisplayName>-element, de gelokaliseerde weergavenaam die aan gebruikers moet worden weergegeven). Vervang zoals gebruikelijk de contoso_demo... bestandsnamen door de namen die geschikt zijn voor uw project en (zeer belangrijk) zorg ervoor dat het .pfx bestand zich niet in de huidige map bevindt (anders zou het zijn gemaakt als onderdeel van uw pakket, inclusief de persoonlijke ondertekeningssleutel!):

    signtool sign /fd SHA256 /a /f ..\contoso_demo_key.pfx ..\contoso_demo.appx
    

    U kunt signtool sign /? typen om te zien wat elke parameter doet, maar in een notendop:

    • /fd stelt het algoritme File Digest (SHA256 is de standaardinstelling voor .appx)
    • /a selecteert automatisch het beste certificaat
    • /f geeft het invoerbestand op dat het handtekeningcertificaat bevat

Ten slotte kunt u nu dubbelklikken op het .appx-bestand om het te installeren, of als u liever de opdrachtregel gebruikt, kunt u een PowerShell-prompt openen, de map met het pakket wijzigen en het volgende typen (waarbij u contoso_demo.appx vervangt door uw pakketnaam):

add-appxpackage contoso_demo.appx

Als u fouten ontvangt over het certificaat dat niet wordt vertrouwd, controleert u of het wordt toegevoegd aan het computerarchief (niet het gebruikersarchief). Als u het certificaat wilt toevoegen aan de certificatenopslag van de computer, kunt u de commandoregel of Windows Verkenner gebruiken.

Om de opdrachtregel te gebruiken:

  1. Voer een opdrachtprompt van Visual Studio 2019 of Visual Studio 2022 uit als beheerder.

  2. Ga naar de map met het .cer-bestand (zorg ervoor dat dit zich buiten uw bron- of projectmappen bevindt!)

  3. Typ de volgende opdracht en vervang contoso_demo.cer door uw bestandsnaam:

    certutil -addstore TrustedPeople contoso_demo.cer
    

    U kunt certutil -addstore /? uitvoeren om te zien wat elke parameter doet, maar in een notendop:

    • -addstore een certificaat toevoegen aan een certificaatarchief
    • TrustedPeople geeft het archief aan waarin het certificaat is geplaatst

Windows Verkenner gebruiken:

  1. Navigeer naar de map met het .pfx-bestand
  2. Dubbelklik op het .pfx bestand en de wizard Certificaat importeren moet worden weergegeven
  3. Kies Local Machine en klik op Next
  4. Accepteer de gebruikersaccountbeheer prompt voor admin elevatie als deze verschijnt, en klik op Next
  5. Voer het wachtwoord voor de persoonlijke sleutel in als er een is en klik op Next
  6. Selecteer Place all certificates in the following store
  7. Klik op Browseen kies de map Trusted People (niet Vertrouwde uitgevers)
  8. Klik op Next en klik vervolgens op Finish

Nadat u het certificaat hebt toegevoegd aan de Trusted People opslag, probeert u het pakket opnieuw te installeren.

U ziet nu dat uw app wordt weergegeven in de lijst 'Alle apps' van het startmenu, met de juiste informatie uit het .resw / .pri-bestand. Als u een lege tekenreeks of de tekenreeks ms-resource:... ziet, is er iets misgegaan. Controleer de bewerkingen opnieuw en controleer of deze juist zijn. Als u met de rechtermuisknop op uw app klikt in het menu Start, kunt u deze vastmaken als tegel en controleren of de juiste informatie daar ook wordt weergegeven.

Stap 1.3: Meer ondersteunde talen toevoegen

Nadat de wijzigingen zijn aangebracht in het pakketmanifest en het eerste resources.resw-bestand is gemaakt, is het toevoegen van extra talen eenvoudig.

Aanvullende gelokaliseerde resources maken

Maak eerst de aanvullende gelokaliseerde resourcewaarden.

Maak in de Strings map extra mappen voor elke taal die u ondersteunt met behulp van de juiste BCP-47-code (bijvoorbeeld Strings\de-DE). Maak in elk van deze mappen een resources.resw bestand (met behulp van een XML-editor of de Visual Studio-ontwerper) die de vertaalde resourcewaarden bevat. Er wordt van uitgegaan dat u al de gelokaliseerde tekenreeksen ergens hebt en dat u ze alleen naar het .resw-bestand moet kopiëren; dit document heeft geen betrekking op de vertaalstap zelf.

Het Strings\de-DE\resources.resw bestand ziet er bijvoorbeeld als volgt uit, waarbij de gemarkeerde tekst is gewijzigd van en-US:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="ApplicationDescription">
    <value>Contoso Demo app with localized resources (German)</value>
  </data>
  <data name="ApplicationDisplayName">
    <value>Contoso Demo Sample (German)</value>
  </data>
  <data name="PackageDisplayName">
    <value>Contoso Demo Package (German)</value>
  </data>
  <data name="PublisherDisplayName">
    <value>Contoso Samples, DE</value>
  </data>
  <data name="TileShortName">
    <value>Contoso (DE)</value>
  </data>
</root>

In de volgende stappen wordt ervan uitgegaan dat u resources hebt toegevoegd voor zowel de-DE als fr-FR, maar hetzelfde patroon kan worden gevolgd voor elke taal.

Het pakketmanifest bijwerken om ondersteunde talen weer te geven

Het pakketmanifest moet worden bijgewerkt om de talen weer te geven die door de app worden ondersteund. Het conversieprogramma voor bureaublad-apps voegt de standaardtaal toe, maar de andere moeten expliciet worden toegevoegd. Als u het AppxManifest.xml bestand rechtstreeks bewerkt, werkt u het Resources knooppunt als volgt bij, voegt u zoveel elementen toe als u nodig hebt en vervangt u de juiste talen die u ondersteunt en zorgt u ervoor dat het eerste item in de lijst de standaardtaal (terugvaltaal) is. In dit voorbeeld is de standaardinstelling Engels (VS) met extra ondersteuning voor zowel Duits (Duitsland) als Frans (Frankrijk):

<Resources>
  <Resource Language="EN-US" />
  <Resource Language="DE-DE" />
  <Resource Language="FR-FR" />
</Resources>

Als u Visual Studio gebruikt, hoeft u niets te doen; als u naar Package.appxmanifest kijkt, ziet u de speciale x-genereren waarde, waardoor het buildproces de talen invoegt die in uw project worden gevonden (op basis van de mappen met BCP-47-codes). Houd er rekening mee dat dit geen geldige waarde is voor een echt pakketmanifest; Het werkt alleen voor Visual Studio-projecten:

<Resources>
  <Resource Language="x-generate" />
</Resources>

Opnieuw bouwen met de gelokaliseerde waarden

Nu kunt u uw toepassing bouwen en implementeren. Als u uw taalvoorkeur wijzigt in Windows, ziet u dat de nieuw gelokaliseerde waarden worden weergegeven in het menu Start (instructies voor het wijzigen van uw taal vindt u hieronder).

Voor Visual Studio kunt u nogmaals Ctrl+Shift+B gebruiken om te bouwen en met de rechtermuisknop op het project te klikken om Deploy.

Als u het project handmatig bouwt, volgt u dezelfde stappen als hierboven, maar voegt u de extra talen, gescheiden door onderstrepingstekens, toe aan de standaardkwalificatielijst (/dq) bij het maken van het configuratiebestand. Als u bijvoorbeeld de Resources Engels, Duits en Frans wilt ondersteunen die in de vorige stap zijn toegevoegd:

makepri createconfig /cf ..\contoso_demo.xml /dq en-US_de-DE_fr-FR /pv 10.0 /o

Hiermee maakt u een PRI-bestand met alle opgegeven talen die u eenvoudig kunt gebruiken voor het testen. Als de totale grootte van uw middelen klein is of als u slechts een klein aantal talen ondersteunt, kan dit acceptabel zijn voor uw verzendapp. Het is alleen wanneer u gebruik wilt maken van de voordelen van het verkleinen van de installatie-/downloadgrootte voor uw middelen, dat u extra werk moet verrichten om afzonderlijke taalpakketten te bouwen.

Testen met de gelokaliseerde waarden

Als u de nieuwe gelokaliseerde wijzigingen wilt testen, voegt u een nieuwe voorkeurstaal voor de gebruikersinterface toe aan Windows. U hoeft geen taalpakketten te downloaden, het systeem opnieuw op te starten of uw volledige Windows-gebruikersinterface in een vreemde taal weer te geven.

  1. De Settings-app (Windows + I) uitvoeren
  2. Ga naar Time & language
  3. Ga naar Region & language
  4. Klik op Add a language
  5. Typ (of selecteer) de gewenste taal (bijvoorbeeld Deutsch )German
    • Als er subtalen zijn, kiest u de gewenste taal (bijvoorbeeld Deutsch / Deutschland)
  6. Selecteer de nieuwe taal in de taallijst
  7. Klik op Set as default

Open nu het startmenu en zoek naar uw toepassing. U ziet nu de gelokaliseerde waarden voor de geselecteerde taal (andere apps worden mogelijk ook gelokaliseerd weergegeven). Als u de gelokaliseerde naam niet meteen ziet, wacht u enkele minuten totdat de cache van het startmenu is vernieuwd. Als u wilt terugkeren naar uw systeemeigen taal, moet u deze de standaardtaal in de taallijst maken.

Stap 1.4: Meer onderdelen van het pakketmanifest lokaliseren (optioneel)

Andere secties van het pakketmanifest kunnen worden gelokaliseerd. Als uw toepassing bijvoorbeeld bestandsextensies verwerkt, moet deze een windows.fileTypeAssociation extensie in het manifest hebben, met behulp van de groen gemarkeerde tekst precies zoals wordt weergegeven (omdat deze naar resources verwijst) en de geel gemarkeerde tekst vervangen door informatie die specifiek is voor uw toepassing:

<Extensions>
  <uap:Extension Category="windows.fileTypeAssociation">
    <uap:FileTypeAssociation Name="default">
      <uap:DisplayName>ms-resource:Resources/FileTypeDisplayName</uap:DisplayName>
      <uap:Logo>Assets\StoreLogo.png</uap:Logo>
      <uap:InfoTip>ms-resource:Resources/FileTypeInfoTip</uap:InfoTip>
      <uap:SupportedFileTypes>
        <uap:FileType ContentType="application/x-contoso">.contoso</uap:FileType>
      </uap:SupportedFileTypes>
    </uap:FileTypeAssociation>
  </uap:Extension>
</Extensions>

U kunt deze informatie ook toevoegen met behulp van Visual Studio Manifest Designer, met behulp van het tabblad Declarations, waarbij u de gemarkeerde waarden van de noteert:

Schermopname van de Visual Studio Manifest Designer die het tabblad Declaraties toont met de tekstvakken Weergavenaam en Infotip gemarkeerd.

Voeg nu de bijbehorende resourcenamen toe aan elk van uw .resw-bestanden, waarbij u de gemarkeerde tekst vervangt door de juiste tekst voor uw app (vergeet niet dit te doen voor elke ondersteunde taal!):

... existing content...
<data name="FileTypeDisplayName">
  <value>Contoso Demo File</value>
</data>
<data name="FileTypeInfoTip">
  <value>Files used by Contoso Demo App</value>
</data>

Dit wordt in delen van de Windows-shell, zoals Verkenner, vervolgens weergegeven:

Schermopname van Verkenner met een tooltip met de tekst bestanden die worden gebruikt door de demo-app van Contoso.

Bouw het pakket en test het net als voorheen, waarbij nieuwe scenario's worden uitgevoerd die de nieuwe UI-tekenreeksen moeten weergeven.

Fase 2: MRT gebruiken om resources te identificeren en te vinden

In de vorige sectie hebt u laten zien hoe u MRT gebruikt om het manifestbestand van uw app te lokaliseren, zodat de Windows Shell de naam en andere metagegevens van de app correct kan weergeven. Hiervoor zijn geen codewijzigingen vereist; het vereist gewoon het gebruik van .resw bestanden en een aantal extra hulpprogramma's. In deze sectie ziet u hoe u MRT gebruikt om resources te vinden in uw bestaande resourceindelingen en hoe u uw bestaande code voor het afhandelen van resources gebruikt met minimale wijzigingen.

Veronderstellingen over bestaande bestandsindeling en toepassingscode

Omdat er veel manieren zijn om Win32 Desktop-apps te lokaliseren, maakt dit document enkele vereenvoudigende veronderstellingen over de structuur van de bestaande toepassing die u moet toewijzen aan uw specifieke omgeving. Mogelijk moet u enkele wijzigingen aanbrengen in uw bestaande codebasis of resource-indeling om te voldoen aan de vereisten van MRT. Deze zijn grotendeels buiten het bereik van dit document.

Indeling van resourcebestand

In dit artikel wordt ervan uitgegaan dat uw gelokaliseerde resources allemaal dezelfde bestandsnamen hebben (bijvoorbeeld contoso_demo.exe.mui of contoso_strings.dll of contoso.strings.xml) maar dat ze in verschillende mappen worden geplaatst met BCP-47-namen (en-US, de-DE, enzovoort). Het maakt niet uit hoeveel resourcebestanden u hebt, wat hun namen zijn, wat hun bestandsindelingen /bijbehorende API's zijn, enzovoort. Het enige wat van belang is, is dat elke logische resource dezelfde bestandsnaam heeft (maar in een andere fysieke map is geplaatst).

Als een tegenvoorbeeld: als uit uw toepassing een platte bestandsstructuur gebruikt met een enkele Resources-map waarin de bestanden english_strings.dll en french_strings.dllzich bevinden, zou deze niet goed passen bij MRT. Een betere structuur is een Resources map met submappen en bestanden en\strings.dll en fr\strings.dll. Het is ook mogelijk om dezelfde basisbestandsnaam te gebruiken, maar met ingesloten kwalificaties, zoals strings.lang-en.dll en strings.lang-fr.dll, maar het gebruik van mappen met de taalcodes is conceptueel eenvoudiger, dus het is waar we ons op richten.

Opmerking

Het is nog steeds mogelijk om MRT en de voordelen van verpakking te gebruiken, zelfs als u deze naamconventie voor bestanden niet kunt volgen; Het vereist gewoon meer werk.

De toepassing kan bijvoorbeeld een set aangepaste UI-opdrachten (gebruikt voor knoplabels enzovoort) hebben in een eenvoudig tekstbestand met de naam ui.txt, ingedeeld onder een UICommands map:

+ ProjectRoot
|--+ Strings
|  |--+ en-US
|  |  \--- resources.resw
|  \--+ de-DE
|     \--- resources.resw
|--+ UICommands
|  |--+ en-US
|  |  \--- ui.txt
|  \--+ de-DE
|     \--- ui.txt
|--- AppxManifest.xml
|--- ...rest of project...

Code voor het laden van resources

In dit artikel wordt ervan uitgegaan dat u op een bepaald moment in uw code het bestand wilt zoeken dat een gelokaliseerde resource bevat, laadt en vervolgens gebruikt. De API's die worden gebruikt om de resources te laden, de API's die worden gebruikt om de resources te extraheren, enzovoort, zijn niet belangrijk. In pseudocode zijn er in feite drie stappen:

set userLanguage = GetUsersPreferredLanguage()
set resourceFile = FindResourceFileForLanguage(MY_RESOURCE_NAME, userLanguage)
set resource = LoadResource(resourceFile) 
    
// now use 'resource' however you want

MRT vereist alleen het wijzigen van de eerste twee stappen in dit proces: hoe u de beste kandidaat-resources bepaalt en hoe u ze vindt. Hiervoor hoeft u niet te wijzigen hoe u de resources laadt of gebruikt (hoewel dit faciliteiten biedt als u hiervan gebruik wilt maken).

De toepassing kan bijvoorbeeld gebruikmaken van de Win32-API-GetUserPreferredUILanguages, de functie CRT sprintfen de Win32-API CreateFile om de drie pseudocodefuncties hierboven te vervangen en vervolgens handmatig het tekstbestand te parseren op zoek naar name=value paren. (De details zijn niet belangrijk; dit is slechts om te illustreren dat MRT geen invloed heeft op de technieken die worden gebruikt voor het verwerken van resources zodra ze zijn gelokaliseerd).

Stap 2.1: Codewijzigingen voor het gebruik van MRT om bestanden te vinden

Het is niet moeilijk om uw code aan te passen naar het gebruik van MRT voor het vinden van resources. Hiervoor moet u een handvol WinRT-typen en een paar regels code gebruiken. De belangrijkste typen die u gaat gebruiken, zijn als volgt:

  • ResourceContext, waarin de huidige actieve set kwalificatiewaarden (taal, schaalfactor, enzovoort) wordt ingekapseld.
  • ResourceManager (de WinRT-versie, niet de .NET-versie), waarmee u toegang hebt tot alle resources uit het PRI-bestand
  • ResourceMap, die een specifieke subset vertegenwoordigt van de resources in het PRI-bestand (in dit voorbeeld de op bestanden gebaseerde resources versus de tekenreeksresources)
  • NamedResource, die een logische bron en al zijn mogelijke kandidaten vertegenwoordigt
  • ResourceCandidate, die één concrete kandidaatresource vertegenwoordigt

In pseudocode is de manier waarop u een bepaalde resourcebestandsnaam (zoals UICommands\ui.txt in het bovenstaande voorbeeld) als volgt kunt oplossen:

// Get the ResourceContext that applies to this app
set resourceContext = ResourceContext.GetForViewIndependentUse()
    
// Get the current ResourceManager (there's one per app)
set resourceManager = ResourceManager.Current
    
// Get the "Files" ResourceMap from the ResourceManager
set fileResources = resourceManager.MainResourceMap.GetSubtree("Files")
    
// Find the NamedResource with the logical filename we're looking for,
// by indexing into the ResourceMap
set desiredResource = fileResources["UICommands\ui.txt"]
    
// Get the ResourceCandidate that best matches our ResourceContext
set bestCandidate = desiredResource.Resolve(resourceContext)
   
// Get the string value (the filename) from the ResourceCandidate
set absoluteFileName = bestCandidate.ValueAsString

Houd er met name rekening mee dat de code geen een specifieke taalmap aanvraagt, zoals UICommands\en-US\ui.txt, ook al bestaan de bestanden op schijf. In plaats daarvan vraagt het om de logische bestandsnaam UICommands\ui.txt en is het afhankelijk van MRT om het juiste on-disk-bestand te vinden in een van de taalmappen.

Vanaf hier kan de voorbeeld-app CreateFile blijven gebruiken om de absoluteFileName te laden en de name=value paren net als voorheen te parseren; deze logica hoeft niet te worden gewijzigd in de app. Als u in C# of C++/CX schrijft, is de werkelijke code niet veel ingewikkelder dan dit (en in feite kunnen veel tussenliggende variabelen worden verwijderd) - zie de sectie over .NET-resources ladenhieronder. C++/WRL-toepassingen zijn complexer vanwege de com-gebaseerde COM-api's op laag niveau die worden gebruikt om de WinRT-API's te activeren en aan te roepen, maar de fundamentele stappen die u uitvoert, zijn hetzelfde: zie de sectie over Win32 MUI-resources laden, hieronder.

.NET-resources laden

Omdat .NET een ingebouwd mechanisme heeft voor het zoeken en laden van resources (ook wel 'Satellietassembly's genoemd), is er geen expliciete code die moet worden vervangen zoals in het bovenstaande synthetische voorbeeld. In .NET hebt u alleen uw resource-DLL's nodig in de juiste mappen en bevinden ze zich automatisch voor u. Wanneer een app is verpakt als een MSIX of .appx met behulp van resourcepakketten, is de mapstructuur enigszins anders. In plaats van dat de resourcemappen submappen van de hoofdmap van de toepassing zijn, staan ze op hetzelfde niveau. Als de gebruiker de taal niet in zijn voorkeuren heeft staan, zijn de resourcemappen mogelijk helemaal niet aanwezig.

Stel u een .NET-toepassing voor met de volgende indeling, waarbij alle bestanden onder de map MainApp staan:

+ MainApp
|--+ en-us
|  \--- MainApp.resources.dll
|--+ de-de
|  \--- MainApp.resources.dll
|--+ fr-fr
|  \--- MainApp.resources.dll
\--- MainApp.exe

Na de conversie naar .appx ziet de indeling er ongeveer als volgt uit, ervan uitgaande dat en-US de standaardtaal was en de gebruiker zowel Duits als Frans heeft vermeld in de taallijst:

+ WindowsAppsRoot
|--+ MainApp_neutral
|  |--+ en-us
|  |  \--- MainApp.resources.dll
|  \--- MainApp.exe
|--+ MainApp_neutral_resources.language_de
|  \--+ de-de
|     \--- MainApp.resources.dll
\--+ MainApp_neutral_resources.language_fr
   \--+ fr-fr
      \--- MainApp.resources.dll

Omdat de gelokaliseerde resources niet meer voorkomen in submappen onder de installatielocatie van het hoofdbestand, mislukt de ingebouwde .NET-resourceomzetting. Gelukkig heeft .NET een goed gedefinieerd mechanisme voor het verwerken van mislukte assemblybelastingspogingen: de AssemblyResolve gebeurtenis. Een .NET-app met behulp van MRT moet zich registreren voor deze gebeurtenis en de ontbrekende assembly voor het .NET-resourcesubsysteem opgeven.

Een beknopt voorbeeld van het gebruik van de WinRT-API's voor het vinden van satellietassembly's die door .NET worden gebruikt, is als volgt; de code zoals deze wordt gepresenteerd, wordt opzettelijk gecomprimeerd om een minimale implementatie weer te geven, hoewel u kunt zien dat deze nauw is toegewezen aan de pseudocode hierboven, waarbij de doorgegeven ResolveEventArgs de naam van de assembly opgeeft die we moeten vinden. Een uitvoerbare versie van deze code (met gedetailleerde opmerkingen en foutafhandeling) vindt u in het bestand PriResourceRsolver.cs in de .NET Assembly Resolver voorbeeld op GitHub.

static class PriResourceResolver
{
  internal static Assembly ResolveResourceDll(object sender, ResolveEventArgs args)
  {
    var fullAssemblyName = new AssemblyName(args.Name);
    var fileName = string.Format(@"{0}.dll", fullAssemblyName.Name);

    var resourceContext = ResourceContext.GetForViewIndependentUse();
    resourceContext.Languages = new[] { fullAssemblyName.CultureName };

    var resource = ResourceManager.Current.MainResourceMap.GetSubtree("Files")[fileName];

    // Note use of 'UnsafeLoadFrom' - this is required for apps installed with .appx, but
    // in general is discouraged. The full sample provides a safer wrapper of this method
    return Assembly.UnsafeLoadFrom(resource.Resolve(resourceContext).ValueAsString);
  }
}

Gezien de bovenstaande klasse voegt u het volgende ergens vroeg toe in de opstartcode van uw toepassing (voordat gelokaliseerde resources moeten worden geladen):

void EnableMrtResourceLookup()
{
  AppDomain.CurrentDomain.AssemblyResolve += PriResourceResolver.ResolveResourceDll;
}

De .NET-runtime genereert de AssemblyResolve gebeurtenis wanneer deze de resource-DLL's niet kan vinden, waarna de opgegeven gebeurtenis-handler het gewenste bestand zoekt via MRT en de assembly retourneert.

Opmerking

Als uw app al een AssemblyResolve handler voor andere doeleinden heeft, moet u de resource-oplossingscode integreren met uw bestaande code.

Win32 MUI-resources aan het laden

Het laden van Win32 MUI-resources is in feite hetzelfde als het laden van .NET-satellietassembly's, maar dan met C++/CX- of C++/WRL-code. Met C++/CX kunt u veel eenvoudigere code gebruiken die nauw overeenkomt met de bovenstaande C#-code, maar maakt gebruik van C++-taalextensies, compilerswitches en extra runtime-overheard die u mogelijk wilt vermijden. Als dat het geval is, biedt het gebruik van C++/WRL een veel lagere oplossing ten koste van uitgebreidere code. Niettemin, als u bekend bent met ATL-programmering (of COM in het algemeen), dan zou WRL vertrouwd aanvoelen.

In de volgende voorbeeldfunctie ziet u hoe u C++/WRL gebruikt om een specifieke bron-DLL te laden en een HINSTANCE te retourneren die kan worden gebruikt om meer resources te laden met behulp van de gebruikelijke Win32-resource-API's. In tegenstelling tot het C#-voorbeeld dat de ResourceContext expliciet initialiseert met de taal die is aangevraagd door de .NET-runtime, is deze code afhankelijk van de huidige taal van de gebruiker.

#include <roapi.h>
#include <wrl\client.h>
#include <wrl\wrappers\corewrappers.h>
#include <Windows.ApplicationModel.resources.core.h>
#include <Windows.Foundation.h>
   
#define IF_FAIL_RETURN(hr) if (FAILED((hr))) return hr;
    
HRESULT GetMrtResourceHandle(LPCWSTR resourceFilePath,  HINSTANCE* resourceHandle)
{
  using namespace Microsoft::WRL;
  using namespace Microsoft::WRL::Wrappers;
  using namespace ABI::Windows::ApplicationModel::Resources::Core;
  using namespace ABI::Windows::Foundation;
    
  *resourceHandle = nullptr;
  HRESULT hr{ S_OK };
  RoInitializeWrapper roInit{ RO_INIT_SINGLETHREADED };
  IF_FAIL_RETURN(roInit);
    
  // Get Windows.ApplicationModel.Resources.Core.ResourceManager statics
  ComPtr<IResourceManagerStatics> resourceManagerStatics;
  IF_FAIL_RETURN(GetActivationFactory(
    HStringReference(
    RuntimeClass_Windows_ApplicationModel_Resources_Core_ResourceManager).Get(),
    &resourceManagerStatics));
    
  // Get .Current property
  ComPtr<IResourceManager> resourceManager;
  IF_FAIL_RETURN(resourceManagerStatics->get_Current(&resourceManager));
    
  // get .MainResourceMap property
  ComPtr<IResourceMap> resourceMap;
  IF_FAIL_RETURN(resourceManager->get_MainResourceMap(&resourceMap));
    
  // Call .GetValue with supplied filename
  ComPtr<IResourceCandidate> resourceCandidate;
  IF_FAIL_RETURN(resourceMap->GetValue(HStringReference(resourceFilePath).Get(),
    &resourceCandidate));
    
  // Get .ValueAsString property
  HString resolvedResourceFilePath;
  IF_FAIL_RETURN(resourceCandidate->get_ValueAsString(
    resolvedResourceFilePath.GetAddressOf()));
    
  // Finally, load the DLL and return the hInst.
  *resourceHandle = LoadLibraryEx(resolvedResourceFilePath.GetRawBuffer(nullptr),
    nullptr, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
    
  return S_OK;
}

Fase 3: Resourcepacks bouwen

Nu u een 'fat pack' hebt die alle resources bevat, zijn er twee paden voor het bouwen van afzonderlijke hoofdpakketten en resourcepakketten om download- en installatiegrootten te minimaliseren:

  • Neem een bestaand vetpakket en voer het uit het hulpprogramma Bundle Generator om automatisch resourcepacks te maken. Dit is de voorkeursbenadering als u een buildsysteem hebt dat al een fat pack produceert en u het wilt nabewerken om de resourcepakketten te genereren.
  • Rechtstreeks de afzonderlijke resourcepakketten produceren en deze inbouwen in een bundel. Dit is de voorkeursbenadering als u meer controle hebt over uw buildsysteem en de pakketten rechtstreeks kunt bouwen.

Stap 3.1: De bundel maken

Het hulpprogramma Bundle Generator gebruiken

Als u het hulpprogramma Bundelgenerator wilt gebruiken, moet het PRI-configuratiebestand dat voor het pakket is gemaakt, handmatig worden bijgewerkt om de sectie <packaging> te verwijderen.

Als u Visual Studio gebruikt, raadpleegt u Controleer of resources op een apparaat zijn geïnstalleerd, ongeacht of een apparaat ze nodig heeft voor informatie over hoe u alle talen in het hoofdpakket kunt opnemen door de bestanden priconfig.packaging.xml en priconfig.default.xmlte maken.

Als u bestanden handmatig bewerkt, voert u de volgende stappen uit:

  1. Maak het configuratiebestand op dezelfde manier als voorheen, waarbij u het juiste pad, de bestandsnaam en talen vervangt:

    makepri createconfig /cf ..\contoso_demo.xml /dq en-US_de-DE_es-MX /pv 10.0 /o
    
  2. Open het gemaakte .xml-bestand handmatig en verwijder de hele sectie &lt;packaging&rt; (maar houd alles intact):

    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
    <resources targetOsVersion="10.0.0" majorVersion="1">
      <!-- Packaging section has been deleted... -->
      <index root="\" startIndexAt="\">
        <default>
        ...
        ...
    
  3. Bouw het .pri-bestand en het .appx-pakket zoals voorheen, met behulp van het bijgewerkte configuratiebestand en de juiste map- en bestandsnamen (zie hierboven voor meer informatie over deze opdrachten):

    makepri new /pr . /cf ..\contoso_demo.xml /of ..\resources.pri /mf AppX /o
    makeappx pack /m AppXManifest.xml /f ..\resources.map.txt /p ..\contoso_demo.appx /o
    
  4. Nadat het pakket is gemaakt, gebruikt u de volgende opdracht om de bundel te maken met behulp van de juiste map- en bestandsnamen:

    BundleGenerator.exe -Package ..\contoso_demo.appx -Destination ..\bundle -BundleName contoso_demo
    

U kunt nu doorgaan naar de laatste stap, ondertekening (zie hieronder).

Resourcepakketten handmatig maken

Voor het handmatig maken van resourcepakketten moet een iets andere set opdrachten worden uitgevoerd om afzonderlijke .pri- en .appx-bestanden te maken. Deze zijn allemaal vergelijkbaar met de opdrachten die hierboven worden gebruikt om fat-pakketten te maken, dus er wordt een minimale uitleg gegeven. Opmerking: bij alle opdrachten wordt ervan uitgegaan dat de huidige map de map is met het AppXManifest.xml bestand, maar alle bestanden worden in de bovenliggende map geplaatst (u kunt indien nodig een andere map gebruiken, maar u mag de projectmap niet vervuilen met een van deze bestanden). Vervang zoals altijd de bestandsnamen 'Contoso' door uw eigen bestandsnamen.

  1. Gebruik de volgende opdracht om een configuratiebestand te maken dat alleen beschouwt als de standaardtaal voor de standaardkwalificatie; in dit geval en-US:

    makepri createconfig /cf ..\contoso_demo.xml /dq en-US /pv 10.0 /o
    
  2. Maak een standaardbestand .pri en .map.txt voor het hoofdpakket, plus een extra set bestanden voor elke taal in uw project, met de volgende opdracht:

    makepri new /pr . /cf ..\contoso_demo.xml /of ..\resources.pri /mf AppX /o
    
  3. Gebruik de volgende opdracht om het hoofdpakket te maken (dat de uitvoerbare code en standaardtaalbronnen bevat). Zoals altijd wijzigt u de naam naar wens, hoewel u het pakket in een afzonderlijke map moet plaatsen om het maken van de bundel later gemakkelijker te maken (in dit voorbeeld wordt de ..\bundle directory gebruikt):

    makeappx pack /m .\AppXManifest.xml /f ..\resources.map.txt /p ..\bundle\contoso_demo.main.appx /o
    
  4. Nadat het hoofdpakket is gemaakt, gebruikt u de volgende opdracht eenmaal voor elke extra taal (herhaal deze opdracht voor elk taaltoewijzingsbestand dat in de vorige stap is gegenereerd). Ook hier moet de uitvoer zich in een afzonderlijke map bevinden (hetzelfde als het hoofdpakket). De taal wordt opgegeven zowel in de optie /f als in de optie /p en het gebruik van het nieuwe /r argument (wat aangeeft dat een resourcepakket gewenst is):

    makeappx pack /r /m .\AppXManifest.xml /f ..\resources.language-de.map.txt /p ..\bundle\contoso_demo.de.appx /o
    
  5. Combineer alle pakketten uit de bundelmap in één .appxbundle bestand. Met de nieuwe /d optie geeft u de map op die moet worden gebruikt voor alle bestanden in de bundel (daarom worden de .appx bestanden in een afzonderlijke map in de vorige stap geplaatst):

    makeappx bundle /d ..\bundle /p ..\contoso_demo.appxbundle /o
    

De laatste stap voor het bouwen van het pakket is ondertekening.

Stap 3.2: de bundel ondertekenen

Nadat u het .appxbundle-bestand hebt gemaakt (via het hulpprogramma Bundelgenerator of handmatig) hebt gemaakt, hebt u één bestand met het hoofdpakket plus alle resourcepakketten. De laatste stap is het ondertekenen van het bestand, zodat Windows het installeert:

signtool sign /fd SHA256 /a /f ..\contoso_demo_key.pfx ..\contoso_demo.appxbundle

Hiermee wordt een ondertekend .appxbundle-bestand geproduceerd dat het hoofdpakket bevat plus alle taalspecifieke resourcepakketten. U kunt dubbelklikken op een pakketbestand om de app te installeren plus alle gewenste taal(en) op basis van de windows-taalvoorkeuren van de gebruiker.