Utiliser le système de gestion des ressources Windows 10 dans une application ou un jeu hérité

Les applications et jeux .NET et Win32 sont souvent localisés dans différentes langues pour développer leur marché adressable total. Pour plus d’informations sur la proposition de valeur de la localisation de votre application, consultez Internationalisation et localisation. En incluant votre application ou jeu .NET ou Win32 dans un package .msix ou .appx, vous pouvez exploiter le système de gestion des ressources pour charger des ressources d’application adaptées au contexte d’exécution. Cette rubrique détaillée décrit ces techniques.

Il existe de nombreuses façons de localiser une application Win32 traditionnelle, mais Windows 8 a introduit un nouveau système de gestion des ressources qui fonctionne dans les langages de programmation, entre les types d’applications et fournit des fonctionnalités sur et au-dessus de la localisation simple. Ce système sera appelé « MRT » dans cette rubrique. Historiquement, il s’est représenté par « Technologie moderne des ressources », mais le terme « Moderne » a été supprimé. Le gestionnaire de ressources peut également être appelé MRM (Modern Resource Manager) ou IRP (index de ressource de package).

Combiné avec le déploiement basé sur MSIX ou .appx (par exemple, à partir du Microsoft Store), MRT peut fournir automatiquement les ressources les plus applicables pour un utilisateur/appareil donné, ce qui réduit la taille de téléchargement et d’installation de votre application. Cette réduction de taille peut être importante pour les applications avec une grande quantité de contenu localisé, peut-être sur l’ordre de plusieurs gigaoctets pour les jeux AAA. Les avantages supplémentaires de MRT incluent les descriptions localisées dans Windows Shell et le Microsoft Store, logique de secours automatique quand la langue préférée d’un utilisateur ne correspond pas à vos ressources disponibles.

Ce document décrit l’architecture générale de MRT et fournit un guide de portage pour aider à déplacer des applications Win32 héritées vers MRT avec des modifications de code minimales. Une fois le passage à MRT effectué, des avantages supplémentaires (tels que la possibilité de segmenter les ressources par facteur d’échelle ou thème système) deviennent disponibles pour le développeur. Notez que la localisation basée sur MRT fonctionne pour les applications UWP et Win32 traitées par le Pont du bureau (appelé « Centennial »).

Dans de nombreuses situations, vous pouvez continuer à utiliser vos formats de localisation et votre code source existants tout en intégrant MRT pour résoudre les ressources au moment de l’exécution et réduire les tailles de téléchargement, ce n’est pas une approche tout ou rien. Le tableau suivant récapitule le travail et les coûts/avantages estimés à chaque stade. Ce tableau n’inclut pas de tâches de non-localisation, telles que la fourniture d’icônes d’application haute résolution ou à contraste élevé. Pour plus d’informations sur la fourniture de plusieurs ressources pour les vignettes, les icônes, etc., consultez Personnaliser vos ressources pour la langue, l’échelle, le contraste élevé et d’autres qualificateurs.

Travailler Avantage Coût estimé
Localiser le manifeste du package Travail minimal nécessaire pour que votre contenu localisé apparaisse dans l’interpréteur de commandes Windows et dans le Microsoft Store Small
Utiliser MRT pour identifier et localiser les ressources Conditions préalables à la réduction des tailles de téléchargement et d’installation ; secours automatique de langue Moyenne
Créer des packs de ressources Étape finale pour réduire les tailles de téléchargement et d’installation Small
Migrer vers des formats et API de ressources MRT Tailles de fichiers beaucoup plus petites (en fonction de la technologie des ressources existante) grand

Introduction

La plupart des applications non triviales contiennent des éléments d’interface utilisateur appelés ressources découplées du code de l’application (contrairement aux valeurs codées en dur créées dans le code source lui-même). Il existe plusieurs raisons de préférer les ressources aux valeurs codées en dur ( facilité de modification par les non-développeurs, par exemple), mais l’une des principales raisons consiste à permettre à l’application de choisir différentes représentations de la même ressource logique au moment de l’exécution. Par exemple, le texte à afficher sur un bouton (ou l’image à afficher dans une icône) peut différer selon la ou les langues que l’utilisateur comprend, les caractéristiques du périphérique d'affichage ou si l’utilisateur dispose de technologies d’assistance activées.

Ainsi, l’objectif principal de toute technologie de gestion des ressources consiste à traduire, au moment de l’exécution, une demande de nom de ressource logique ou symbolique (tel que SAVE_BUTTON_LABEL) en la meilleure valeur réelle possible (par exemple, « Enregistrer ») à partir d'un ensemble de candidats possibles (par exemple, « Enregistrer », « Speichern », or « 저장 »). MRT fournit une telle fonction et permet aux applications d’identifier les candidats aux ressources à l’aide d’un large éventail d’attributs, appelés qualificateurs, tels que la langue de l’utilisateur, le facteur d'échelle d’affichage, le thème sélectionné par l’utilisateur et d’autres facteurs environnementaux. MRT prend même en charge les qualificateurs personnalisés pour les applications qui en ont besoin (par exemple, une application peut fournir différentes ressources graphiques pour les utilisateurs qui se sont connectés avec un compte et les utilisateurs invités, sans ajouter explicitement cette case activée dans chaque partie de leur application). MRT fonctionne avec les ressources de chaîne et les ressources basées sur des fichiers, où les ressources basées sur des fichiers sont implémentées en tant que références aux données externes (les fichiers eux-mêmes).

Exemple

Voici un exemple simple d’application qui a des étiquettes de texte sur deux boutons (openButton et saveButton) et un fichier PNG utilisé pour un logo (logoImage). Les étiquettes de texte sont localisées en anglais et en allemand, et le logo est optimisé pour les affichages de bureau normaux (facteur d’échelle de 100 %) et les téléphones haute résolution (facteur d’échelle de 300 %). Notez que ce diagramme présente une vue conceptuelle générale du modèle ; elle ne mappe pas exactement à l’implémentation.

Screenshot of a Source code label, a Lookup table label, and a Files on disk label.

Dans le graphique, le code de l’application fait référence aux trois noms de ressources logiques. Au moment de l’exécution, la pseudo-fonction GetResource utilise MRT pour rechercher ces noms de ressources dans la table de ressources (appelée fichier IRP) et trouver le candidat le plus approprié en fonction des conditions ambiantes (langue de l’utilisateur et facteur d’échelle de l’affichage). Dans le cas des étiquettes, les chaînes sont utilisées directement. Dans le cas de l’image du logo, les chaînes sont interprétées comme des noms de fichiers et les fichiers sont lus sur le disque.

Si l’utilisateur parle une langue autre que l’anglais ou l’allemand ou a un facteur d’échelle d’affichage autre que 100 % ou 300 %, MRT choisit le candidat correspondant le plus proche en fonction d’un ensemble de règles de secours (consultez système de gestion des ressources pour plus d’arrière-plan).

Notez que MRT prend en charge les ressources adaptées à plusieurs qualificateurs - par exemple, si l’image de logo contenait également du texte incorporé qui devait également être localisé, le logo aurait quatre candidats : EN/Scale-100, DE/Scale-100, EN/Scale-300 et DE/Scale-300.

Sections de ce document

Les sections suivantes décrivent les tâches générales requises pour intégrer MRT à votre application.

Phase 0 : générer un package d’application

Cette section explique comment créer votre application bureautique existante en tant que package d’application. Aucune fonctionnalité MRT n’est utilisée à ce stade.

Phase 1 : localiser le manifeste de l’application

Cette section explique comment localiser le manifeste de votre application (afin qu’il apparaisse correctement dans l’interpréteur de commandes Windows) tout en utilisant votre format de ressource hérité et votre API pour empaqueter et localiser des ressources.

Phase 2 : utiliser MRT pour identifier et localiser les ressources

Cette section explique comment modifier votre code d’application (et éventuellement la disposition des ressources) pour localiser les ressources à l’aide de MRT, tout en utilisant vos formats de ressources et API existants pour charger et consommer les ressources.

Phase 3 : créer des packs de ressources

Cette section décrit les dernières modifications nécessaires pour séparer vos ressources en packs de ressources distincts, ce qui réduit la taille de téléchargement (et d’installation) de votre application.

Non abordé dans ce document

Une fois les phases 0-3 ci-dessus terminées, vous disposez d’une application « bundle » qui peut être envoyée au Microsoft Store et qui réduit la taille du téléchargement et de l’installation pour les utilisateurs en omettant les ressources dont ils n’ont pas besoin (par exemple, les langues qu’ils ne parlent pas). D’autres améliorations de la taille et des fonctionnalités de l’application peuvent être apportées en effectuant une dernière étape.

Phase 4 : migrer vers des formats de ressources MRT et des API

Cette phase dépasse le cadre de ce document ; cela implique de déplacer vos ressources (en particulier les chaînes) à partir de formats hérités tels que des DLL MUI ou des assemblys de ressources .NET dans des fichiers IRP. Cela peut entraîner d’autres économies d’espace pour les tailles de téléchargement et d’installation. Il permet également d’utiliser d’autres fonctionnalités MRT, telles que la réduction du téléchargement et de l’installation des fichiers image en fonction du facteur d’échelle, des paramètres d’accessibilité, etc.

Phase 0 : générer un package d’application

Avant d’apporter des modifications aux ressources de votre application, vous devez d’abord remplacer votre technologie d’empaquetage et d’installation actuelle par la technologie de déploiement et d’empaquetage UWP standard. Pour vous inscrire, trois méthodes s’offrent à vous.

  • Si vous disposez d’une application bureautique volumineuse avec un programme d’installation complexe ou si vous utilisez de nombreux points d’extension du système d’exploitation, vous pouvez utiliser l’outil Desktop App Converter pour générer la disposition et les informations de manifeste de fichier UWP à partir de votre programme d’installation d’application existant (par exemple, une MSI).
  • Si vous disposez d’une application bureautique plus petite avec relativement peu de fichiers ou un programme d’installation simple et qu’aucun hook d’extensibilité n’est possible, vous pouvez créer manuellement les informations de disposition et de manifeste de fichier.
  • Si vous régénérez à partir de la source et souhaitez mettre à jour votre application pour qu’elle soit une application UWP pure, vous pouvez créer un projet dans Visual Studio et vous appuyer sur l’IDE pour effectuer une grande partie du travail pour vous.

Si vous souhaitez utiliser Desktop App Converter, consultez Packager une application bureautique à l’aide du convertisseur d’applications de bureau pour plus d’informations sur le processus de conversion. Vous trouverez un ensemble complet d’exemples Desktop Converter sur le Pont du bureau vers le dépôt GitHub d’exemples UWP.

Si vous souhaitez créer manuellement le package, vous devez créer une structure d’annuaires qui inclut tous les fichiers de votre application (exécutables et contenus, mais pas le code source) et un fichier manifeste du package (.appxmanifest). Vous trouverez un exemple dans l’exemple Hello, World GitHub, mais un fichier manifeste du package de base qui exécute l’exécutable de bureau nommé ContosoDemo.exe est le suivant, où le texte mis en surbrillance sera remplacé par vos propres valeurs.

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

Pour plus d’informations sur le fichier manifeste du package et la disposition du package, consultez le manifeste du package d’application.

Enfin, si vous utilisez Visual Studio pour créer un projet et migrer votre code existant, consultez Créer une application « Hello, world ». Vous pouvez inclure votre code existant dans le nouveau projet, mais vous devrez probablement apporter des modifications significatives au code (en particulier dans l’interface utilisateur) afin de s’exécuter en tant qu’application UWP pure. Ces modifications n'entrent pas dans l’étendue du présent document.

Phase 1 : localiser le manifeste

Étape 1.1 : mettre à jour des chaînes et des ressources dans le manifeste

Dans la phase 0, vous avez créé un fichier manifeste du package de base (.appxmanifest) pour votre application (en fonction des valeurs fournies au convertisseur, extraites de l’interface MSI ou saisies manuellement dans le manifeste), mais elle ne contiendra pas d’informations localisées, ni ne prendra en charge les fonctionnalités supplémentaires telles que les ressources de vignette de démarrage haute résolution, etc.

Pour vous assurer que le nom et la description de votre application sont correctement localisés, vous devez définir certaines ressources dans un ensemble de fichiers de ressources et mettre à jour le manifeste du package pour les référencer.

Création d’un fichier de ressources par défaut

La première étape consiste à créer un fichier de ressources par défaut dans votre langue par défaut (par exemple, anglais américain). Vous pouvez le faire manuellement avec un éditeur de texte ou via le Concepteur de ressources dans Visual Studio.

Si vous souhaitez créer les ressources manuellement :

  1. Créez un fichier XML nommé resources.resw et placez-le dans un sous-dossier Strings\en-us de votre projet. Utilisez le code BCP-47 approprié si votre langue par défaut n’est pas l’anglais américain.
  2. Dans le fichier XML, ajoutez le contenu suivant, où le texte mis en surbrillance est remplacé par le texte approprié pour votre application, dans votre langue par défaut.

Remarque

Il existe des restrictions sur les longueurs de certaines de ces chaînes. Pour plus d’informations, consultez VisualElements.

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

Si vous souhaitez utiliser le concepteur dans Visual Studio :

  1. Créez le dossier Strings\en-us (ou autre langue appropriée) dans votre projet et ajoutez un nouvel élément au dossier racine de votre projet, en utilisant le nom par défaut resources.resw. Veillez à choisir Le fichier de ressources (.resw) et non le dictionnaire de ressources. Un dictionnaire de ressources est un fichier utilisé par les applications XAML.
  2. À l’aide du concepteur, saisir les chaînes suivantes (utilisez la même Names mais remplacez Values par le texte approprié pour votre application) :

Screenshot showing the Resources.resw file showing the Name and Value columns. for the resources.

Remarque

Si vous commencez avec le concepteur Visual Studio, vous pouvez toujours modifier le code XML directement en appuyant sur F7. Toutefois, si vous commencez par un fichier XML minimal, le concepteur ne reconnaît pas le fichier, car il manque beaucoup de métadonnées supplémentaires. Vous pouvez le corriger en copiant les informations XSD réutilisables d’un fichier généré par le concepteur dans votre fichier XML modifié manuellement.

Mettre à jour le manifeste pour référencer les ressources

Une fois les valeurs définies dans le fichier .resw, l’étape suivante consiste à mettre à jour le manifeste pour référencer les chaînes de ressources. Là encore, vous pouvez modifier un fichier XML directement ou vous appuyer sur le Concepteur de manifeste Visual Studio.

Si vous modifiez directement du code XML, ouvrez le fichier AppxManifest.xml et apportez les modifications suivantes aux valeurs mises en surbrillance : utilisez ce texte exact, et non pas un texte spécifique à votre application. Il n’est pas nécessaire d’utiliser ces noms de ressources exacts, vous pouvez choisir vos propres noms, mais ce que vous choisissez doit correspondre exactement à ce qui se trouve dans le fichier .resw. Ces noms doivent correspondre aux Names que vous avez créés dans le fichier .resw, précédés du schéma ms-resource: et de l’espace de noms Resources/.

Remarque

De nombreux éléments du manifeste ont été omis de cet extrait de code - ne supprimez rien !

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

Si vous utilisez le concepteur de manifeste Visual Studio, ouvrez le fichier .appxmanifest et modifiez les valeurs de valeurs mises en surbrillance dans l’onglet *Application et l’onglet Empaquetage :

Screenshot of the Visual Studio Manifest Designer showing the Application tab with the Display name and Description text boxes called out.

Screenshot of the Visual Studio Manifest Designer showing the Packaging tab with the Package display name and Publisher display name text boxes called out.

Étape 1.2 : générer un fichier IRP, créer un package MSIX et vérifier qu’il fonctionne

Vous devez maintenant être en mesure de générer le fichier .pri et de déployer l’application pour vérifier que les informations appropriées (dans votre langue par défaut) apparaissent dans le menu Démarrer.

Si vous générez dans Visual Studio, appuyez simplement sur Ctrl+Shift+B pour générer le projet, puis cliquez avec le bouton droit sur le projet et choisissez Deploy dans le menu local.

Si vous générez manuellement, procédez comme suit pour créer un fichier de configuration pour l’outil MakePRI et générer le fichier .pri lui-même (vous trouverez plus d’informations dans l’empaquetage d’applications manuelles) :

  1. Ouvrez une invite de commandes développeur à partir du dossier Visual Studio 2017 ou Visual Studio 2019 dans le menu Démarrer.

  2. Basculez vers le répertoire racine du projet (celui qui contient le fichier .appxmanifest et le dossier Chaînes ).

  3. Tapez la commande suivante, en remplaçant « contoso_demo.xml » par un nom adapté à votre projet, et « en-US » par la langue par défaut de votre application (ou conservez-la en-US le cas échéant). Notez que le fichier XML est créé dans l’annuaire parent (pas dans l’annuaire du projet), car il ne fait pas partie de l’application (vous pouvez choisir n’importe quel autre annuaire souhaité, mais veillez à remplacer cela dans les commandes ultérieures).

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

    Vous pouvez taper makepri createconfig /? pour voir ce que fait chaque paramètre, mais en résumé :

    • /cf définit le nom de fichier de configuration (la sortie de cette commande)
    • /dq définit les qualificateurs par défaut, dans ce cas la langue en-US
    • /pv définit la version de la plateforme, dans ce cas Windows 10
    • /o définit celui-ci pour remplacer le fichier de sortie s’il existe
  4. Maintenant que vous disposez d’un fichier de configuration, réexécutez-les MakePRI pour rechercher les ressources et les empaqueter dans un fichier IRP. Remplacez « contoso_demop.xml » par le nom de fichier XML que vous avez utilisé à l’étape précédente et veillez à spécifier l’annuaire parent pour l’entrée et la sortie :

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

    Vous pouvez saisir makepri new /? pour voir ce que fait chaque paramètre, mais en un mot :

    • /pr définit la racine du projet (dans ce cas, le répertoire actif)
    • /cf définit le nom de fichier de configuration, créé à l’étape précédente
    • /of définit le fichier de sortie
    • /mf crée un fichier de mappage (afin que nous puissions exclure des fichiers dans le package dans une étape ultérieure)
    • /o définit celui-ci pour remplacer le fichier de sortie s’il existe
  5. Vous disposez maintenant d’un .pri fichier avec les ressources linguistiques par défaut (par exemple, en-US). Pour vérifier que le keytab est correct, vous pouvez exécuter la commande suivante :

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

    Vous pouvez saisir makepri dump /? pour voir ce que fait chaque paramètre, mais en un mot :

    • /if définit le nom de fichier d’entrée
    • /of définit le nom de fichier de sortie (.xml sera ajouté automatiquement)
    • /o définit celui-ci pour remplacer le fichier de sortie s’il existe
  6. Enfin, vous pouvez ouvrir ..\resources.xml dans un éditeur de texte et vérifier qu’il répertorie vos valeurs <NamedResource> (comme ApplicationDescription et PublisherDisplayName) ainsi <Candidate> que les valeurs de votre langue par défaut choisie (il y aura d’autres contenus au début du fichier ; ignorez-le pour l’instant).

Vous pouvez ouvrir le fichier de mappage ..\resources.map.txt pour vérifier qu’il contient les fichiers nécessaires pour votre projet (y compris le fichier IRP, qui ne fait pas partie de l’annuaire du projet). Il est important de noter que le fichier de mappage n’inclut pas de référence à votre fichier resources.resw, car le contenu de ce fichier a déjà été incorporé dans le fichier IRP. Toutefois, elle contiendra d’autres ressources telles que les noms de fichiers de vos images.

Générer et signer le package partiellement alloué

Maintenant que le fichier IRP est généré, vous pouvez générer et signer le package :

  1. Pour créer le package de l’application, exécutez la commande suivante en remplaçant contoso_demo.appx par le nom du fichier .msix/.appx que vous souhaitez créer et en veillant à choisir un autre annuaire pour le fichier (cet exemple utilise l’annuaire parent ; il peut être n’importe où, mais ne doit pas être l’annuaire du projet).

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

    Vous pouvez saisir makeappx pack /? pour voir ce que fait chaque paramètre, mais en un mot :

    • /m définit le fichier manifeste à utiliser
    • /f définit le fichier de mappage à utiliser (créé à l'étape précédente)
    • /p définit le nom du package de sortie
    • /o définit celui-ci pour remplacer le fichier de sortie s’il existe
  2. Une fois le package créé, il doit être signé. Le moyen le plus simple d’obtenir un certificat de signature consiste à créer un projet Windows universel vide dans Visual Studio et à copier le fichier .pfx qu’il crée, mais vous pouvez en créer un manuellement à l’aide des services MakeCert et des utilitaires Pvk2Pfx, comme décrit dans Comment créer un certificat de signature de package d’application.

    Important

    Si vous créez manuellement un certificat de signature, veillez à placer les fichiers dans un annuaire différent de celui de votre projet source ou de votre source de package. Sinon, il peut être inclus dans le cadre du package, y compris la clé privée !

  3. Utilisez la commande suivante pour générer le package. Notez que le Publisher spécifié dans l'élément Identity du AppxManifest.xml doit correspondre au Subject du certificat (il ne s'agit pas de l'élément <PublisherDisplayName>, qui est le nom complet localisé à montrer aux utilisateurs). Comme d’habitude, remplacez les noms contoso_demo... par les noms appropriés pour votre projet, et (très important) assurez-vous que le fichier .pfx n’est pas dans le répertoire actif (sinon il aurait été créé dans le cadre de votre package, y compris la clé de signature privée !) :

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

    Vous pouvez saisir signtool sign /? pour voir ce que fait chaque paramètre, mais en un mot :

    • /fd définit l’algorithme File Digest (SHA256 est la valeur par défaut pour .appx)
    • /a sélectionne automatiquement le meilleur certificat
    • /f spécifie le fichier d’entrée qui contient le certificat de signature

Enfin, vous pouvez maintenant double-cliquer sur le fichier .appx pour l’installer, ou si vous préférez la ligne de commande, vous pouvez ouvrir une invite PowerShell, passer à l’annuaire contenant le package et taper ce qui suit (en remplaçant contoso_demo.appx par le nom de votre package) :

add-appxpackage contoso_demo.appx

Si vous recevez des erreurs concernant le certificat non approuvé, vérifiez qu’il est ajouté au magasin d’ordinateurs (et non au magasin d’utilisateurs). Pour ajouter le certificat au magasin d’ordinateurs, vous pouvez utiliser la ligne de commande ou l’Explorateur Windows.

Pour utiliser la ligne de commande :

  1. Exécutez une invite de commandes Visual Studio 2017 ou Visual Studio 2019 en tant qu’Administration istrateur.

  2. Basculez vers l’annuaire qui contient le fichier .cer (n’oubliez pas de vous assurer que cela se trouve en dehors de vos annuaires source ou projet !)

  3. Tapez la commande suivante, en remplaçant contoso_demo.cer par votre nom de fichier :

    certutil -addstore TrustedPeople contoso_demo.cer
    

    Vous pouvez exécuter certutil -addstore /? pour voir ce que fait chaque paramètre, mais en un mot :

    • -addstore ajoute un certificat à un magasin de certificats
    • TrustedPeople indique le magasin dans lequel le certificat est placé

Fermez l'Explorateur Windows.

  1. Naviguez vers le dossier qui contient le fichier .pfx
  2. Double-cliquez sur le fichier .pfx et l’Assistant Importation de certificat doit apparaître
  3. Choisir Local Machine et cliquer Next
  4. Acceptez l’invite d’élévation de l’administrateur du contrôle de compte d’utilisateur, le cas échéant, puis cliquez sur Next
  5. Entrez le mot de passe de la clé privée, s’il en existe un, puis cliquez sur Next
  6. Sélectionnez Place all certificates in the following store
  7. Cliquez sur Browse, puis choisissez le Trusted People dossier (et non « Éditeurs approuvés »)
  8. Cliquez sur Next puis sur Finish

Après avoir ajouté le certificat au store Trusted People, réessayez d’installer le package.

Vous devez maintenant voir votre application apparaître dans la liste « Toutes les applications » du menu Démarrer, avec les informations correctes du fichier .resw / .pri. Si vous voyez une chaîne vide ou la chaîne ms-resource:..., un problème s’est produit : double case activée vos modifications et assurez-vous qu’elles sont correctes. Si vous cliquez avec le bouton droit sur votre application dans le menu Démarrer, vous pouvez l’épingler en tant que vignette et vérifier que les informations appropriées s’affichent également.

Étape 1.3 : ajouter d’autres langues prises en charge

Une fois que les modifications ont été apportées au manifeste du package et que le fichier initial resources.resw a été créé, l’ajout de langues supplémentaires est facile.

Créer des ressources localisées supplémentaires

Tout d’abord, créez les valeurs de ressources localisées supplémentaires.

Dans le Strings dossier, créez des dossiers supplémentaires pour chaque langue que vous prenez en charge à l’aide du code BCP-47 approprié (par exemple). Strings\de-DE Dans chacun de ces dossiers, créez un resources.resw fichier (à l’aide d’un éditeur XML ou du concepteur Visual Studio) qui inclut les valeurs de ressources traduites. Il est supposé que vous disposez déjà des chaînes localisées disponibles quelque part, et que vous devez simplement les copier dans le fichier .resw ; ce document ne couvre pas l’étape de traduction elle-même.

Par exemple, le Strings\de-DE\resources.resw fichier peut ressembler à ceci, avec le texte mis en surbrillance modifié à partir de 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>

Les étapes suivantes supposent que vous avez ajouté des ressources pour les deux de-DE et fr-FR, mais le même modèle peut être suivi pour n’importe quelle langue.

Mettre à jour le manifeste du package pour répertorier les langues prises en charge

Le manifeste du package doit être mis à jour pour répertorier les langues prises en charge par l’application. Desktop App Converter ajoute la langue par défaut, mais les autres doivent être ajoutés explicitement. Si vous modifiez directement le AppxManifest.xml fichier, mettez à jour le Resources nœud comme suit, en ajoutant autant d’éléments que nécessaire, en remplaçant les langues appropriées que vous prenez en charge et en veillant à ce que la première entrée de la liste soit la langue par défaut (secours). Dans cet exemple, la valeur par défaut est l’anglais (US) avec une prise en charge supplémentaire pour l’allemand (Allemagne) et Français (France) :

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

Si vous utilisez Visual Studio, vous n’avez pas besoin de faire quoi que ce soit ; si vous examinez Package.appxmanifest, la valeur de génération x spéciale, ce qui entraîne l’insertion des langues dans votre projet (en fonction des dossiers nommés avec des codes BCP-47). Notez qu’il ne s’agit pas d’une valeur valide pour un manifeste du package réel ; il fonctionne uniquement pour les projets Visual Studio :

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

Recréer avec les valeurs localisées

Vous pouvez maintenant générer et déployer votre application, à nouveau, et si vous modifiez votre préférence de langue dans Windows, vous devez voir les valeurs nouvellement localisées apparaître dans le menu Démarrer (des instructions pour modifier votre langue sont ci-dessous).

Pour Visual Studio, là encore, vous pouvez simplement utiliser Ctrl+Shift+B pour générer, puis cliquer avec le bouton droit sur le projet Deploy.

Si vous générez manuellement le projet, suivez les mêmes étapes que celles ci-dessus, mais ajoutez les langues supplémentaires, séparées par des traits de soulignement, à la liste des qualificateurs par défaut (/dq) lors de la création du fichier de configuration. Par exemple, pour prendre en charge les ressources anglais, allemand et Français ajoutées à l’étape précédente :

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

Cela crée un fichier IRP qui contient toutes les langues spécifiées que vous pouvez facilement utiliser pour les tests. Si la taille totale de vos ressources est petite ou que vous ne prenez en charge qu’un petit nombre de langues, cela peut être acceptable pour votre application d’expédition ; ce n’est que si vous souhaitez réduire la taille d’installation/téléchargement de vos ressources que vous devez effectuer pour créer des modules linguistiques distincts.

Tester avec les valeurs localisées

Pour tester les nouvelles modifications localisées, vous ajoutez simplement une nouvelle langue d’interface utilisateur préférée à Windows. Il n’est pas nécessaire de télécharger les modules linguistiques, de redémarrer le système ou d’afficher l’ensemble de votre interface utilisateur Windows dans une langue étrangère.

  1. Exécutez l’application Settings (Windows + I)
  2. Accédez à Time & language
  3. Accédez à Region & language
  4. Cliquez sur Add a language
  5. Tapez (ou sélectionnez) la langue souhaitée (par exemple Deutsch ou German)
  • S’il existe des sous-langues, choisissez celle souhaitée (par exemple, Deutsch / Deutschland)
  1. Sélectionnez la nouvelle langue dans la liste des langues
  2. Cliquez sur Set as default

Ouvrez maintenant le menu Démarrer et recherchez votre application, et vous devez voir les valeurs localisées pour la langue sélectionnée (d’autres applications peuvent également apparaître localisées). Si vous ne voyez pas le nom localisé immédiatement, attendez quelques minutes jusqu’à ce que le cache du menu Démarrer soit actualisé. Pour revenir au langage natif, il vous suffit de le rendre la langue par défaut dans la liste des langues.

Étape 1.4 : localisation d’autres parties du manifeste du package (facultatif)

D’autres sections du manifeste du package peuvent être localisées. Par exemple, si votre application gère les extensions de fichiers, elle doit avoir une extension windows.fileTypeAssociation dans le manifeste, en utilisant le texte en surbrillance vert exactement comme indiqué (car elle fait référence à des ressources) et en remplaçant le texte en surbrillance jaune par des informations spécifiques à votre application :

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

Vous pouvez également ajouter ces informations à l’aide du Concepteur de manifeste Visual Studio, à l’aide de l’onglet Declarations, en prenant note des valeurs mises en surbrillance :

Screenshot of the Visual Studio Manifest Designer showing the Declarations tab with the Display name and Info tip text boxes called out.

Ajoutez maintenant les noms de ressources correspondants à chacun de vos .resw fichiers, en remplaçant le texte mis en surbrillance par le texte approprié pour votre application (n’oubliez pas de le faire pour chaque langue prise en charge !) :

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

Cela s’affiche ensuite dans certaines parties de l’interpréteur de commandes Windows, telles que Explorateur de fichiers :

Screenshot of File Explorer showing a tooltip that says Files used by Contoso Demo App.

Générez et testez le package comme avant, en faisant l’exercice de tous les nouveaux scénarios qui doivent afficher les nouvelles chaînes d’interface utilisateur.

Phase 2 : utiliser MRT pour identifier et localiser les ressources

La section précédente a montré comment utiliser MRT pour localiser le fichier manifeste de votre application afin que Windows Shell puisse afficher correctement le nom de l’application et d’autres métadonnées. Aucune modification du code n’a été nécessaire pour cela ; il suffit d’utiliser des fichiers .resw et d’autres outils. Cette section montre comment utiliser MRT pour localiser des ressources dans vos formats de ressources existants et utiliser votre code de gestion des ressources existant avec des modifications minimales.

Hypothèses relatives à la disposition de fichier existante et au code d’application

Étant donné qu’il existe de nombreuses façons de localiser des applications Win32 Desktop, ce document simplifie certaines hypothèses sur la structure de l’application existante que vous devrez mapper à votre environnement spécifique. Vous devrez peut-être apporter des modifications à votre disposition de code ou de ressource existante pour respecter les exigences de MRT, et celles-ci sont largement hors de portée pour ce document.

Fichier de ressources de disposition

Cet article suppose que vos ressources localisées ont tous les mêmes noms de fichiers (par exemple, contoso_demo.exe.mui ou contoso_strings.dllcontoso.strings.xml) mais qu’elles sont placées dans différents dossiers avec des noms BCP-47 (en-US, de-DE, etc.). Il n’importe pas combien de fichiers de ressources vous avez, quels sont leurs noms, quels sont leurs formats de fichiers / API associées, etc. La seule chose qui importe est que chaque ressource logique a le même nom de fichier (mais placé dans un autre annuaire physique).

Par exemple, si votre application utilise une structure de fichiers plate avec un seul annuaire Resources contenant les fichiers english_strings.dll et french_strings.dll, elle ne s'adaptera pas bien à la MRT. Une meilleure structure serait un annuaire Resources avec des sous-répertoires et des fichiers en\strings.dll et fr\strings.dll. Il est également possible d’utiliser le même nom de fichier de base, mais avec des qualificateurs incorporés, tels que strings.lang-en.dll et strings.lang-fr.dll, mais l’utilisation de répertoires avec les codes de langage est conceptuellement plus simple, c’est ce que nous allons nous concentrer sur.

Remarque

Il est toujours possible d’utiliser MRT et les avantages de l’empaquetage même si vous ne pouvez pas suivre cette convention d’affectation de noms de fichiers ; cela nécessite juste plus de travail.

Par exemple, l’application peut avoir un ensemble de commandes d’interface utilisateur personnalisées (utilisées pour les étiquettes de boutons, etc.) dans un fichier texte simple nommé ui.txt, disposé sous un dossier UICommands :

+ 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 de chargement des ressources

Cet article suppose qu’à un moment donné dans votre code, vous souhaitez localiser le fichier qui contient une ressource localisée, le charger, puis l’utiliser. Les API utilisées pour charger les ressources, les API utilisées pour extraire les ressources, etc. ne sont pas importantes. En pseudocode, il existe essentiellement trois étapes :

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

MRT nécessite uniquement de modifier les deux premières étapes de ce processus : la façon dont vous déterminez les meilleures ressources candidates et la façon dont vous les trouvez. Il ne vous oblige pas à modifier la façon dont vous chargez ou utilisez les ressources (même s’il fournit des installations pour le faire si vous souhaitez en tirer parti).

Par exemple, l’application peut utiliser l’API GetUserPreferredUILanguagesWin32, la fonction sprintfCRT et l’API CreateFile Win32 pour remplacer les trois fonctions pseudocode ci-dessus, puis analyser manuellement le fichier texte à la recherche name=value de paires. (Les détails ne sont pas importants ; il s’agit simplement d’illustrer que MRT n’a aucun impact sur les techniques utilisées pour gérer les ressources une fois qu’elles ont été localisées).

Étape 2.1 : modifications du code permettant d’utiliser MRT pour localiser les fichiers

Le basculement de votre code pour utiliser MRT pour localiser les ressources n’est pas difficile. Il nécessite l’utilisation d’un certain nombre de types WinRT et de quelques lignes de code. Les principaux types que vous utiliserez sont les suivants :

  • ResourceContext, qui encapsule l’ensemble actif de valeurs de qualificateur (langage, facteur d’échelle, etc.)
  • ResourceManager (version WinRT, et non la version .NET), qui permet d’accéder à toutes les ressources à partir du fichier IRP
  • ResourceMap, qui représente un sous-ensemble spécifique des ressources dans le fichier IRP (dans cet exemple, les ressources basées sur les fichiers et les ressources de chaîne)
  • NamedResource, qui représente une ressource logique et tous ses candidats possibles
  • ResourceCandidate, qui représente une seule ressource candidate concrète

Dans le pseudo-code, la façon dont vous devez résoudre un nom de fichier de ressource donné (comme UICommands\ui.txt dans l’exemple ci-dessus) est la suivante :

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

Notez en particulier que le code ne demande pas de dossier de langage spécifique, par exemple UICommands\en-US\ui.txt, même s’il s’agit de la façon dont les fichiers existent sur le disque. Au lieu de cela, il demande le nom de fichier UICommands\ui.txt logique et s’appuie sur MRT pour trouver le fichier sur disque approprié dans l’un des répertoires linguistiques.

À partir de là, l’exemple d’application peut continuer à utiliser CreateFile pour charger les paires absoluteFileName et analyser les paires name=valuecomme avant ; aucune de cette logique n’a besoin de changer dans l’application. Si vous écrivez en C# ou C++/CX, le code réel n’est pas beaucoup plus compliqué que cela (et, en fait, la plupart des variables intermédiaires peuvent être supprimées) - consultez la section sur le chargement des ressources .NET, ci-dessous. Les applications basées sur C++/WRL seront plus complexes en raison des API COM de bas niveau utilisées pour activer et appeler les API WinRT, mais les étapes fondamentales que vous effectuez sont les mêmes : consultez la section sur le chargement des ressources MUI Win32, ci-dessous.

Chargement des ressources .NET

Étant donné que .NET dispose d’un mécanisme intégré pour localiser et charger des ressources (appelées « Assemblys satellites »), il n’existe aucun code explicite à remplacer comme dans l’exemple synthétique ci-dessus : dans .NET, vous avez simplement besoin de dll de ressources dans les répertoires appropriés et ils sont automatiquement situés pour vous. Lorsqu’une application est empaquetée en tant que MSIX ou .appx à l’aide de packs de ressources, la structure d’annuaires est un peu différente, plutôt que de faire en sorte que les annuaires de ressources soient des sous-répertoires du répertoire d’application principal, ils sont homologues (ou ne sont pas présents du tout si l’utilisateur n’a pas la langue répertoriée dans ses préférences).

Par exemple, imaginez une application .NET avec la disposition suivante, où tous les fichiers existent sous le MainApp dossier :

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

Après la conversion en .appx, la disposition ressemblera à ceci, en supposant que la en-US était la langue par défaut et que l’utilisateur a à la fois l’allemand et le français répertoriés dans leur liste de langues :

+ 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

Étant donné que les ressources localisées n’existent plus dans les sous-répertoires sous l’emplacement d’installation du fichier exécutable principal, la résolution de ressources .NET intégrée échoue. Heureusement, .NET dispose d’un mécanisme bien défini pour gérer les tentatives de chargement d’assembly ayant échoué : l’événement AssemblyResolve. Une application .NET utilisant MRT doit s’inscrire pour cet événement et fournir l’assembly manquant pour le sous-système de ressources .NET.

Voici un exemple concis d’utilisation des API WinRT pour localiser les assemblys satellites utilisés par .NET ; le code tel qu’il est présenté est intentionnellement compressé pour afficher une implémentation minimale, bien que vous puissiez le voir mapper étroitement au pseudo-code ci-dessus, avec le passage ResolveEventArgs, en fournissant le nom de l’assembly que nous devons localiser. Vous trouverez une version exécutable de ce code (avec des commentaires détaillés et une gestion des erreurs) dans le fichier PriResourceRsolver.cs de l’exemple de programme de résolution d’assembly .NET sur 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);
  }
}

Étant donné la classe ci-dessus, vous devez ajouter le code de démarrage de votre application à un emplacement précoce dans le code de démarrage de votre application (avant que toutes les ressources localisées doivent être chargées) :

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

Le runtime .NET déclenche l’événement AssemblyResolve chaque fois qu’il ne trouve pas les DLL de ressource, à quel moment le gestionnaire d’événements fourni localisera le fichier souhaité via MRT et retournera l’assembly.

Remarque

Si votre application dispose déjà d’un AssemblyResolve gestionnaire à d’autres fins, vous devez intégrer le code de résolution des ressources à votre code existant.

Chargement des ressources MUI Win32

Le chargement des ressources MUI Win32 est essentiellement identique au chargement d’assemblys satellites .NET, mais à l’aide de code C++/CX ou C++/WRL à la place. L’utilisation de C++/CX permet un code beaucoup plus simple qui correspond étroitement au code C# ci-dessus, mais il utilise des extensions de langage C++, des commutateurs de compilateur et un runtime supplémentaire entendu, vous pouvez éviter. Si c’est le cas, l’utilisation de C++/WRL offre une solution à impact beaucoup plus faible au coût d’un code plus détaillé. Néanmoins, si vous êtes familiarisé avec la programmation ATL (ou COM en général), WRL doit se sentir familier.

L’exemple de fonction suivant montre comment utiliser C++/WRL pour charger une DLL de ressource spécifique et retourner une HINSTANCE ressource qui peut être utilisée pour charger d’autres ressources à l’aide des API de ressources Win32 habituelles. Notez que contrairement à l’exemple C# qui initialise explicitement ResourceContext avec la langue demandée par le runtime .NET, ce code s’appuie sur la langue actuelle de l’utilisateur.

#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;
}

Phase 3 : création de packs de ressources

Maintenant que vous disposez d’un « fat pack » qui contient toutes les ressources, il existe deux chemins vers la création de packages principaux et de packages de ressources distincts afin de réduire les tailles de téléchargement et d’installation :

  • Prenez un pack fat existant et exécutez-le via l’outil Bundle Generator pour créer automatiquement des packs de ressources. Il s’agit de l’approche recommandée si vous avez un système de build qui produit déjà un pack gras et que vous souhaitez la post-traiter pour générer les packs de ressources.
  • Produisez directement les packages de ressources individuels et générez-les dans un bundle. Il s’agit de l’approche recommandée si vous avez plus de contrôle sur votre système de build et que vous pouvez générer les packages directement.

Étape 3.1 : créer le bundle

Utilisation de l’outil Bundle Generator

Pour utiliser l’outil Bundle Generator, le fichier config IRP créé pour le package doit être mis à jour manuellement pour supprimer la section <packaging>.

Si vous utilisez Visual Studio, reportez-vous à Vérifier que les ressources sont installées sur un appareil, qu’elles soient requises pour obtenir des informations sur la façon de générer toutes les langues dans le package principal en créant les fichiers priconfig.packaging.xml et priconfig.default.xml.

Si vous modifiez manuellement des fichiers, procédez comme suit :

  1. Créez le fichier de configuration de la même façon que précédemment, en remplaçant le chemin d’accès, le nom de fichier et les langues appropriés :

    makepri createconfig /cf ..\contoso_demo.xml /dq en-US_de-DE_es-MX /pv 10.0 /o
    
  2. Ouvrez manuellement le fichier créé .xml et supprimez l’intégralité &lt;packaging&rt; de la section (mais conservez tout le reste 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. Générez le fichier .pri et le package .appx comme avant, à l’aide du fichier de configuration mis à jour et de l’annuaire et des noms de fichiers appropriés (voir ci-dessus pour plus d’informations sur ces commandes) :

    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. Une fois le package créé, utilisez la commande suivante pour créer le bundle, en utilisant les noms d’annuaire et de fichier appropriés :

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

Vous pouvez maintenant passer à l’étape finale, signature (voir ci-dessous).

Création manuelle de packages de ressources

La création manuelle de packages de ressources nécessite l’exécution d’un ensemble légèrement différent de commandes pour générer des fichiers distincts .pri et .appx des fichiers. Ces commandes sont toutes similaires aux commandes utilisées ci-dessus pour créer des packages gras, de sorte qu’une explication minimale est donnée. Remarque : toutes les commandes supposent que le répertoire actif est l’annuaire contenant le fichier AppXManifest.xml, mais tous les fichiers sont placés dans l’annuaire parent (vous pouvez utiliser un autre annuaire, si nécessaire, mais vous ne devez pas polluer l’annuaire du projet avec l’un de ces fichiers). Comme toujours, remplacez les noms de fichiers « Contoso » par vos propres noms de fichiers.

  1. Utilisez la commande suivante pour créer un fichier de configuration qui nomme uniquement la langue par défaut comme qualificateur par défaut, dans ce cas : en-US

    makepri createconfig /cf ..\contoso_demo.xml /dq en-US /pv 10.0 /o
    
  2. Créez un fichier par défaut .pri et .map.txt pour le package principal, ainsi qu’un ensemble supplémentaire de fichiers pour chaque langue trouvée dans votre projet, avec la commande suivante :

    makepri new /pr . /cf ..\contoso_demo.xml /of ..\resources.pri /mf AppX /o
    
  3. Utilisez la commande suivante pour créer le package principal (qui contient le code exécutable et les ressources linguistiques par défaut). Comme toujours, modifiez le nom comme vous le voyez, bien que vous deviez placer le package dans un annuaire distinct pour faciliter la création du bundle plus tard (cet exemple utilise l’annuaire ..\bundle) :

    makeappx pack /m .\AppXManifest.xml /f ..\resources.map.txt /p ..\bundle\contoso_demo.main.appx /o
    
  4. Une fois le package principal créé, utilisez la commande suivante une fois pour chaque langue supplémentaire (par exemple, répétez cette commande pour chaque fichier de mappage de langue généré à l’étape précédente). Là encore, la sortie doit se trouver dans un annuaire distinct (identique à celui du package principal). Notez que la langue est spécifiée à la fois dans l’option /f et dans l’option /p, ainsi que l’utilisation du nouvel argument /r (ce qui indique qu’un package de ressources est souhaité) :

    makeappx pack /r /m .\AppXManifest.xml /f ..\resources.language-de.map.txt /p ..\bundle\contoso_demo.de.appx /o
    
  5. Combinez tous les packages de l’annuaire de bundle dans un seul fichier .appxbundle. La nouvelle option /d spécifie l’annuaire à utiliser pour tous les fichiers du bundle (c’est pourquoi les fichiers .appx sont placés dans un annuaire distinct à l’étape précédente) :

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

La dernière étape de création du package est la signature.

Étape 3.2 : signature de l’offre groupée

Une fois que vous avez créé le fichier .appxbundle (via l’outil Bundle Generator ou manuellement), vous disposez d’un fichier unique qui contient le package principal et tous les packages de ressources. La dernière étape consiste à signer le fichier afin que Windows l’installe :

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

Cela produit un fichier signé .appxbundle qui contient le package principal ainsi que tous les packages de ressources spécifiques à la langue. Il peut être double-cliqué comme un fichier de package pour installer l’application, ainsi que toutes les langues appropriées en fonction des préférences de langue Windows de l’utilisateur.