Verwenden des Ressourcenverwaltungssystems für Windows 10 in älteren Apps oder Spielen
.NET- und Win32-Apps und -Spiele werden häufig in verschiedene Sprachen lokalisiert, um ihren gesamten adressierbaren Markt zu erweitern. Weitere Informationen zu einer Werterhöhung Ihrer App durch Lokalisierung finden Sie unter Globalisierung und Lokalisierung. Indem Sie Ihre .NET- oder Win32-App oder Ihr Spiel als MSIX- oder AppX-Paket verpacken, können Sie das Ressourcenverwaltungssystem nutzen, um App-Ressourcen zu laden, die auf den Laufzeitkontext zugeschnitten sind. In diesem Thema werden die Techniken detailliert beschrieben.
Es gibt viele Möglichkeiten, eine herkömmliche Win32-Anwendung zu lokalisieren, aber Windows 8 hat ein neues Ressourcenverwaltungssystem eingeführt, das über Programmiersprachen und Anwendungstypen hinweg funktioniert und Funktionen bietet, die über die einfache Lokalisierung hinausgehen. Dieses System wird in diesem Thema als „MRT“ bezeichnet. Historisch gesehen stand das für „Modern Resource Technology“, aber der Begriff „Modern“ wurde inzwischen abgeschafft. Der Ressourcen-Manager kann auch als MRM (Modern Resource Manager) oder PRI (Package Resource Index) bekannt sein.
In Kombination mit einer MSIX- oder .appx-basierten Bereitstellung (z. B. aus dem Microsoft Store) kann MRT automatisch die für einen bestimmten Benutzer / ein bestimmtes Gerät am besten geeigneten Ressourcen bereitstellen, wodurch die Download- und Installationsgröße Ihrer Anwendung minimiert wird. Diese Größenreduzierung kann für Anwendungen mit einer großen Menge lokalisierter Inhalte erheblich sein, vielleicht sogar in der Größenordnung von mehreren Gigabyte für AAA-Spiele. Zu den weiteren Vorteilen von MRT gehören lokalisierte Listen in Windows Shell und im Microsoft Store, eine automatische Fallback-Logik, wenn die bevorzugte Sprache eines Benutzers nicht mit Ihren verfügbaren Ressourcen übereinstimmt.
Dieses Dokument beschreibt die High-Level-Architektur von MRT und bietet einen Portierungsleitfaden, der dabei hilft, ältere Win32-Anwendungen mit minimalen Codeänderungen auf MRT zu übertragen. Sobald der Wechsel zu MRT vollzogen ist, stehen dem Entwickler zusätzliche Vorteile zur Verfügung (z. B. die Möglichkeit, Ressourcen nach Skalierungsfaktor oder Systemthema zu segmentieren). Beachten Sie, dass die MRT-basierte Lokalisierung sowohl für UWP-Anwendungen als auch für Win32-Anwendungen funktioniert, die vom Desktop-Brücke (auch als „Centennial“ bezeichnet) verarbeitet werden.
In vielen Situationen können Sie Ihre bestehenden Lokalisierungsformate und Ihren Quellcode weiter verwenden und gleichzeitig MRT zur Auflösung von Ressourcen zur Laufzeit und zur Minimierung der Downloadgröße einbinden - es ist kein Alles-oder-Nichts-Ansatz. In der folgenden Tabelle werden der Arbeitsaufwand und die geschätzten Kosten/Nutzen der einzelnen Phasen zusammengefasst. Diese Tabelle enthält keine Nichtlokalisierungsaufgaben, z.B. das Bereitstellen von Symbolen mit hoher Auflösung oder hoher Kontrastanwendung. Weitere Informationen zum Bereitstellen mehrerer Ressourcen für Kacheln, Symbole usw. finden Sie unter Anpassen Ihrer Ressourcen für Sprache, Skalierung, hohen Kontrast und andere Qualifizierer.
Arbeit | Vorteil | Geschätzte Kosten |
---|---|---|
Lokalisieren des Paketmanifests | Erforderliche Mindestarbeit, damit Ihre lokalisierten Inhalte in der Windows-Shell und im Microsoft Store angezeigt werden | Klein |
Verwenden von MRT zum Identifizieren und Suchen von Ressourcen | Voraussetzung für die Minimierung von Download- und Installationsgrößen; Automatisches Sprachrückfallback | Medium |
Erstellen von Ressourcenpaketen | Letzter Schritt zum Minimieren der Download- und Installationsgrößen | Klein |
Migrieren zu MRT-Ressourcenformaten und APIs | Wesentlich kleinere Dateigrößen (je nach vorhandener Ressourcentechnologie) | Groß |
Einführung
Die meisten nicht trivialen Anwendungen enthalten Elemente der Benutzeroberfläche, die als Ressourcen bezeichnet werden, die vom Code der Anwendung entkoppelt werden (im Gegensatz zu hartcodierten Werten, die im Quellcode selbst erstellt wurden). Es gibt mehrere Gründe, Ressourcen vor hartcodierten Werten zu bevorzugen - z.B. einfache Bearbeitung von Nichtentwicklern - aber einer der wichtigsten Gründe besteht darin, der Anwendung die Auswahl verschiedener Darstellungen derselben logischen Ressource zur Laufzeit zu ermöglichen. Zum Beispiel kann der auf einer Schaltfläche anzuzeigende Text (oder das in einem Symbol anzuzeigende Bild) unterschiedlich sein, je nachdem, welche Sprache(n) der Benutzer versteht, welche Eigenschaften das Anzeigegerät hat oder ob der Benutzer irgendwelche Hilfstechnologien aktiviert hat.
Daher ist der Hauptzweck jeder Ressourcenverwaltungs-Technologie, zur Laufzeit eine Anforderung für einen logischen oder symbolischen Ressourcennamen (z. B. SAVE_BUTTON_LABEL
) in den bestmöglichen aktuellen Wert (z.B. „Speichern“) aus einer Reihe möglicher Kandidaten zu übersetzen (z.B. „Save“, „Speichern“ oder „저장“). MRT bietet eine solche Funktion und ermöglicht Anwendungen die Identifizierung von Ressourcenkandidaten anhand einer Vielzahl von Attributen, den so genannten Qualifikatoren, wie z.B. der Sprache des Benutzers, dem Skalierungsfaktor der Anzeige, dem vom Benutzer gewählten Thema und anderen Umgebungsfaktoren. MRT unterstützt sogar benutzerdefinierte Qualifizierer für Anwendungen, die sie benötigen (z.B. könnte eine Anwendung unterschiedliche Grafikressourcen für Benutzer bereitstellen, die sich mit einem Konto oder Gastbenutzer angemeldet haben, ohne diese Überprüfung explizit in jeden Teil ihrer Anwendung hinzuzufügen). MRT funktioniert sowohl mit Zeichenketten-Ressourcen als auch mit dateibasierten Ressourcen, wobei dateibasierte Ressourcen als Verweise auf die externen Daten (die Dateien selbst) implementiert werden.
Beispiel
Hier ist ein einfaches Beispiel für eine Anwendung, die Textbeschriftungen auf zwei Schaltflächen (openButton
und saveButton
) und eine PNG-Datei enthält, die für ein Logo (logoImage
) verwendet wird. Die Textbeschriftungen sind in Englisch und Deutsch lokalisiert, und das Logo ist für normale Desktop-Displays (100% Skalierungsfaktor) und hochauflösende Telefone (300% Skalierungsfaktor) optimiert. Beachten Sie, dass dieses Diagramm eine übergeordnete, konzeptionelle Ansicht des Modells darstellt; es lässt sich nicht exakt auf die Implementierung übertragen.
In der Grafik verweist die Anwendungscode-Referenz auf die drei logischen Ressourcennamen. Zur Runtime verwendet die GetResource
Pseudofunktion MRT, um diese Ressourcennamen in der Ressourcentabelle (als PRI-Datei bezeichnet) nachzuschlagen und den am besten geeigneten Kandidaten basierend auf den Umgebungsbedingungen (der Sprache des Benutzers und dem Skalierungsfaktor der Anzeige) zu finden. Im Fall der Bezeichnungen werden die Zeichenketten direkt verwendet. Im Fall des Logobilds werden die Zeichenketten als Dateinamen interpretiert, und die Dateien werden vom Datenträger gelesen.
Wenn der Benutzer eine andere Sprache als Englisch oder Deutsch spricht oder einen anderen Skalierungsfaktor als 100 % oder 300 % aufweist, wählt MRT den „nächstgelegenen“ übereinstimmenden Kandidaten basierend auf einer Reihe von Fallbackregeln (siehe Ressourcenverwaltungssystem für mehr Hintergrund).
Beachten Sie, dass MRT Ressourcen unterstützt, die auf mehrere Qualifizierer zugeschnitten sind. Wenn das Logobild beispielsweise eingebetteten Text enthielt, der ebenfalls lokalisiert werden musste, hätte das Logo vier Kandidaten: EN/Scale-100, DE/Scale-100, EN/Scale-300 und DE/Scale-300.
Abschnitte in diesem Dokument
In den folgenden Abschnitten werden die wichtigsten Aufgaben beschrieben, die für die Integration von MRT in Ihre Anwendung erforderlich sind.
Phase 0: Erstellen eines Anwendungspakets
In diesem Abschnitt wird beschrieben, wie Sie Ihre vorhandene Desktopanwendung als Anwendungspaket erstellen. In dieser Phase werden keine MRT-Features verwendet.
Phase 1: Lokalisieren des Anwendungsmanifests
In diesem Abschnitt wird beschrieben, wie Sie das Manifest Ihrer Anwendung lokalisieren (sodass sie in der Windows-Shell korrekt angezeigt wird), während Sie weiterhin das legacy-Ressourcenformat und die API zum Packen und Suchen von Ressourcen verwenden.
Phase 2: Verwenden von MRT zum Identifizieren und Suchen von Ressourcen
In diesem Abschnitt wird beschrieben, wie Sie den Anwendungscode (und möglicherweise das Ressourcenlayout) ändern, um Ressourcen mithilfe von MRT zu suchen, während Sie weiterhin vorhandene Ressourcenformate und APIs verwenden, um die Ressourcen zu laden und zu verbrauchen.
Phase 3: Erstellen von Ressourcenpaketen
In diesem Abschnitt werden die endgültigen Änderungen beschrieben, die erforderlich sind, um Ihre Ressourcen in separate Ressourcenpakete zu trennen, wodurch die Downloadgröße (und die Installationsgröße) Ihrer App minimiert wird.
Dies wird in diesem Dokument nicht behandelt
Nach Abschluss der oben beschriebenen Phasen 0-3 verfügen Sie über ein Anwendungs-„Bündel“, das an den Microsoft Store übermittelt werden kann und die Download- und Installationsgröße für Benutzer minimiert, indem Sie die Ressourcen weglassen, die nicht benötigt werden (z.B. Sprachen, die Sie nicht sprechen). Weitere Verbesserungen der Anwendungsgröße und -funktionalität können durch einen letzten Schritt vorgenommen werden.
Phase 4: Migrieren zu MRT-Ressourcenformaten und APIs
Diese Phase liegt außerhalb des Umfangs dieses Dokuments; Sie beinhaltet das Verschieben Ihrer Ressourcen (insbesondere Zeichenketten) aus älteren Formaten wie MUI-DLLs oder .NET-Ressourcenassemblys in PRI-Dateien. Dies kann zu weiteren Speicherplatzeinsparungen für Download- und Installationsgrößen führen. Sie ermöglicht auch die Verwendung anderer MRT-Features, z.B. die Minimierung des Downloads und das Installieren von Bilddateien basierend auf Skalierungsfaktor, Barrierefreiheitseinstellungen usw.
Phase 0: Erstellen eines Anwendungspakets
Bevor Sie Änderungen an den Ressourcen Ihrer Anwendung vornehmen, müssen Sie zuerst die aktuelle Verpackungs- und Installationstechnologie durch die standardmäßige UWP-Verpackungs- und Bereitstellungstechnologie ersetzen. Dafür stehen drei Möglichkeiten zur Verfügung:
- Wenn Sie über eine große Desktopanwendung mit einem komplexen Installationsprogramm verfügen oder viele Erweiterungspunkte des Betriebssystems verwenden, können Sie das Desktop App Converter-Tool verwenden, um das UWP-Dateilayout und die Manifestinformationen aus Ihrem vorhandenen App-Installationsprogramm zu generieren (z.B. eine MSI-Datei).
- Wenn Sie eine kleinere Desktopanwendung mit relativ wenigen Dateien oder einem einfachen Installationsprogramm und keine Erweiterungshaken haben, können Sie das Dateilayout und die Manifestinformationen manuell erstellen.
- Wenn Sie Ihre Anwendung vom Quellcode aus neu erstellen und sie als reine UWP-Anwendung aktualisieren möchten, können Sie ein neues Projekt in Visual Studio erstellen und sich darauf verlassen, dass die IDE einen Großteil der Arbeit für Sie erledigt.
Wenn Sie den Desktop App Converter verwenden möchten, finden Sie weitere Informationen zum Konvertierungsprozess unter Packen einer Desktopanwendung mit dem Desktop App Converter. Eine vollständiges Satz von Desktop Converter-Beispielen finden Sie in Desktop-Brücke zu UWP-Beispielen GitHub-Repository.
Wenn Sie das Paket manuell erstellen möchten, müssen Sie eine Verzeichnisstruktur erstellen, die alle Dateien Ihrer Anwendung (ausführbare Dateien und Inhalte, jedoch keinen Quellcode) und eine Paketmanifestdatei (.appxmanifest) enthält. Ein Beispiel finden Sie im Beispiel Hallo Welt GitHub, aber eine grundlegende Paketmanifestdatei, die die ausführbare Desktopdatei ContosoDemo.exe
ausführt, ist wie folgt, wobei der hervorgehobene Text durch Ihre eigenen Werte ersetzt wird.
<?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>
Weitere Informationen zur Paketmanifestdatei und zum Paketlayout finden Sie unter App-Paketmanifest.
Wenn Sie schließlich Visual Studio verwenden, um ein neues Projekt zu erstellen und Ihren vorhandenen Code zu migrieren, lesen Sie Erstellen einer „Hallo Welt“-App. Sie können Ihren vorhandenen Code in das neue Projekt einschließen, müssen aber wahrscheinlich erhebliche Codeänderungen vornehmen (insbesondere in der Benutzeroberfläche), um als reine UWP-App ausgeführt zu werden. Diese Änderungen werden im vorliegenden Dokument nicht behandelt.
Phase 1: Lokalisieren des Manifests
Schritt 1.1: Aktualisieren von Zeichenketten und Ressourcen im Manifest
In Phase 0 haben Sie ein einfaches Paketmanifest (.appxmanifest) für Ihre Anwendung erstellt (basierend auf den Werten, die Sie dem Konverter zur Verfügung gestellt, aus dem MSI extrahiert oder manuell in das Manifest eingegeben haben), aber es enthält weder lokalisierte Informationen noch unterstützt es zusätzliche Funktionen wie hochauflösende Startkachel-Ressourcen usw.
Um sicherzustellen, dass der Name und die Beschreibung Ihrer Anwendung richtig lokalisiert sind, müssen Sie einige Ressourcen in einer Reihe von Ressourcendateien definieren und das Paketmanifest so aktualisieren, dass auf sie verwiesen wird.
Erstellen einer Standard-Ressourcendatei
Der erste Schritt besteht darin, eine Standard-Ressourcendatei in Ihrer Standardsprache (z.B. US-Englisch) zu erstellen. Sie können dies entweder manuell mit einem Text-Editor oder über den Ressourcen-Designer in Visual Studio tun.
Wenn Sie die Ressourcen manuell erstellen möchten:
- Erstellen Sie eine XML-Datei namens
resources.resw
, und platzieren Sie sie in einemStrings\en-us
Unterordner Ihres Projekts. Verwenden Sie den entsprechenden BCP-47-Code, wenn Ihre Standardsprache nicht US-Englisch ist. - Fügen Sie in der XML-Datei den folgenden Inhalt hinzu, in dem der hervorgehobene Text durch den entsprechenden Text in Ihrer Standardspache für Ihre App ersetzt wird.
Hinweis
Es gibt Einschränkungen für die Länge einiger dieser Zeichenketten. Weitere Informationen finden Sie unter 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>
Wenn Sie den Designer in Visual Studio verwenden möchten:
- Erstellen Sie den
Strings\en-us
Ordner (oder ggf. eine andere Sprache) in Ihrem Projekt, und fügen Sie dem Stammordner des Projekts ein neues Element hinzu, wobei Sie den Standardnamen vonresources.resw
verwenden. Stellen Sie sicher, dass Sie die Ressourcendatei (.resw) und nicht das Ressourcenwörterbuch auswählen – ein Ressourcenwörterbuch ist eine Datei, die von XAML-Anwendungen verwendet wird. - Geben Sie mit dem Designer die folgenden Zeichenketten ein (verwenden Sie die gleiche
Names
, ersetzen Sie aber dieValues
mit dem entsprechenden Text für Ihre Anwendung):
Hinweis
Wenn Sie mit dem Visual Studio Designer beginnen, können Sie die XML-Datei immer direkt bearbeiten, indem Sie auf F7
drücken. Wenn Sie jedoch mit einer minimalen XML-Datei beginnen, erkennt der Designer die Datei nicht, da viele zusätzliche Metadaten fehlen. Sie können dies beheben, indem Sie die XSD-Kesselsteininformationen aus einer von Designer generierten Datei in Ihre von Hand bearbeitete XML-Datei kopieren.
Aktualisieren des Manifests, um auf die Ressourcen zu verweisen
Nachdem Sie die Werte in der .resw
Datei definiert haben, besteht der nächste Schritt darin, das Manifest zu aktualisieren, um auf die Ressourcen-Zeichenketten zu verweisen. Auch hier können Sie eine XML-Datei direkt bearbeiten oder auf den Manifest-Designer von Visual Studio zurückgreifen.
Wenn Sie XML direkt bearbeiten, öffnen Sie die AppxManifest.xml
Datei, und nehmen Sie die folgenden Änderungen an den hervorgehobenen Werten vor – verwenden Sie diesen genauen Text, nicht textspezifisch für Ihre Anwendung. Es ist nicht erforderlich, diese genauen Ressourcennamen zu verwenden – Sie können ihre eigenen auswählen – aber alles, was Sie auswählen, muss genau mit dem übereinstimmen, was in der .resw
Datei enthalten ist. Diese Namen sollten mit dem Names
in der .resw
Datei erstellten Namen übereinstimmen, dem ms-resource:
Schema und dem Resources/
Namespace vorangestellt.
Hinweis
Viele Elemente des Manifests wurden aus diesem Ausschnitt weggelassen - löschen Sie nichts!
<?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>
Wenn Sie den Manifest-Designer von Visual Studio verwenden, öffnen Sie die .appxmanifest-Datei, und ändern Sie die hervorgehobenen Werte auf der Registerkarte *Anwendung und der Registerkarte Verpackung:
Schritt 1.2: Erstellen einer PRI-Datei, Erstellen eines MSIX-Pakets und Überprüfung, ob es funktioniert
Sie sollten nun in der Lage sein, die .pri
Datei zu erstellen und die Anwendung bereitzustellen, um zu überprüfen, ob die richtigen Informationen (in Ihrer Standardsprache) im Startmenü angezeigt werden.
Wenn Sie in Visual Studio erstellen, drücken Sie einfach Ctrl+Shift+B
, um das Projekt zu erstellen, und klicken Sie dann mit der rechten Maustaste auf das Projekt, und wählen Sie Deploy
im Kontextmenü aus.
Wenn Sie manuell erstellen, führen Sie die folgenden Schritte aus, um eine Konfigurationsdatei für MakePRI
das Tool zu erstellen und die .pri
Datei selbst zu generieren (weitere Informationen finden Sie in Manuelle App-Verpackung):
Öffnen Sie eine Entwickler-Eingabeaufforderung aus dem Ordner Visual Studio 2017 oder Visual Studio 2019 im Startmenü.
Wechseln Sie zum Projekt-Stammverzeichnis (das Verzeichnis, das die appxmanifest-Datei und den Ordner Strings enthält).
Geben Sie den folgenden Befehl ein, und ersetzen Sie „contoso_demo.xml“ durch einen Namen, der für Ihr Projekt geeignet ist, und „en-US“ durch die Standardsprache Ihrer App (oder behalten Sie sie ggf. en-US bei). Beachten Sie, dass die XML-Datei im übergeordneten Verzeichnis (nicht im Projektverzeichnis) erstellt wird, da sie nicht Teil der Anwendung ist (Sie können ein beliebiges anderes Verzeichnis auswählen, aber achten Sie darauf, dies in zukünftigen Befehlen zu ersetzen).
makepri createconfig /cf ..\contoso_demo.xml /dq en-US /pv 10.0 /o
Sie können
makepri createconfig /?
eingeben, um zu sehen, was jeder Parameter tut, aber in Zusammenfassung:/cf
Legt den Konfigurationsdateinamen (die Ausgabe dieses Befehls) fest/dq
Legt die Standardqualifizierer fest, in diesem Fall die Spracheen-US
/pv
Legt die Plattformversion fest, in diesem Fall Windows 10/o
Legt fest, dass die Ausgabedatei überschrieben wird, wenn sie existiert
Jetzt haben Sie eine Konfigurationsdatei, führen Sie erneut
MakePRI
aus, um den Datenträger nach Ressourcen zu durchsuchen und sie in eine PRI-Datei zu packen. Ersetzen Sie „contoso_demop.xml“ durch den XML-Dateinamen, den Sie im vorherigen Schritt verwendet haben, und geben Sie unbedingt das übergeordnete Verzeichnis für Eingabe und Ausgabe an:makepri new /pr . /cf ..\contoso_demo.xml /of ..\resources.pri /mf AppX /o
Sie können
makepri new /?
eingeben, um zu sehen, was jeder Parameter tut, aber kurz gefasst:/pr
Legt den Projektstamm fest (in diesem Fall das aktuelle Verzeichnis)/cf
Legt den Konfigurationsdateinamen fest, der im vorherigen Schritt erstellt wurde/of
Legt die Ausgabedatei fest./mf
Erstellt eine Zuordnungsdatei (sodass Dateien im Paket in einem späteren Schritt ausgeschlossen werden können)/o
Legt fest, dass die Ausgabedatei überschrieben wird, wenn sie existiert
Jetzt verfügen Sie über eine
.pri
Datei mit den Standardsprachen-Ressourcen (z.B. en-US). Um zu überprüfen, ob es richtig funktioniert hat, können Sie den folgenden Befehl ausführen:makepri dump /if ..\resources.pri /of ..\resources /o
Sie können
makepri dump /?
eingeben, um zu sehen, was jeder Parameter tut, aber kurz gefasst:/if
Legt den Eingabedateinamen fest./of
Legt den Ausgabedateinamen fest (.xml
wird automatisch angefügt)/o
Legt fest, dass die Ausgabedatei überschrieben wird, wenn sie existiert
Schließlich können Sie in einem Text-Editor
..\resources.xml
öffnen und überprüfen, ob Ihre<NamedResource>
Werte (wieApplicationDescription
undPublisherDisplayName
) zusammen mit<Candidate>
Werten für die ausgewählte Standardsprache aufgelistet werden (es gibt andere Inhalte am Anfang der Datei; ignorieren Sie dies für den Moment).
Sie können die Zuordnungsdatei ..\resources.map.txt
öffnen, um zu überprüfen, ob sie die für Ihr Projekt erforderlichen Dateien enthält (einschließlich der PRI-Datei, die nicht Teil des Verzeichnisses des Projekts ist). Wichtig ist, dass die Zuordnungsdatei keinen Verweis auf Ihre resources.resw
Datei enthält, da der Inhalt dieser Datei bereits in die PRI-Datei eingebettet wurde. Sie enthält jedoch andere Ressourcen wie die Dateinamen Ihrer Bilder.
Erstellen und Signieren des Pakets
Da nun die PRI-Datei erstellt wurde, können Sie das Paket erstellen und signieren:
Um das App-Paket zu erstellen, führen Sie den folgenden Befehl aus: Ersetzen Sie dabei
contoso_demo.appx
durch den Namen der .msix/.appx-Datei, die Sie erstellen möchten, und stellen Sie sicher, dass Sie ein anderes Verzeichnis für die Datei wählen (in diesem Beispiel wird das übergeordnete Verzeichnis verwendet; es kann überall sein, sollte aber nicht das Projektverzeichnis sein).makeappx pack /m AppXManifest.xml /f ..\resources.map.txt /p ..\contoso_demo.appx /o
Sie können
makeappx pack /?
eingeben, um zu sehen, was jeder Parameter tut, aber kurz gefasst:/m
Legt die zu verwendende Manifestdatei fest./f
Legt die zu verwendende Mapping-Datei fest (die im vorherigen Schritt erstellt wurde)/p
Legt den Ausgabepaketnamen fest./o
Legt fest, dass die Ausgabedatei überschrieben wird, wenn sie existiert
Nachdem das Paket erstellt wurde, muss es signiert werden. Die einfachste Möglichkeit zum Abrufen eines Signaturzertifikats besteht darin, ein leeres universelles Windows-Projekt in Visual Studio zu erstellen und die von ihr erstellte
.pfx
Datei zu kopieren. Sie können jedoch ein Zertifikat manuell mit denMakeCert
undPvk2Pfx
Hilfsprogrammen erstellen, wie in So erstellen Sie ein Signaturzertifikat für ein App-Paket beschrieben.Wichtig
Wenn Sie ein Signaturzertifikat manuell erstellen, stellen Sie sicher, dass Sie die Dateien in einem anderen Verzeichnis als Ihr Quellprojekt oder Ihre Paketquelle ablegen, da es sonst eventuell als Teil des Pakets eingeschlossen wird, einschließlich des privaten Schlüssels!
Verwenden Sie den folgenden Befehl, um das Paket zu erstellen. Beachten Sie, dass die
Publisher
, die im ElementIdentity
derAppxManifest.xml
angegeben ist, mit derSubject
des Zertifikats übereinstimmen muss (dies ist nicht das<PublisherDisplayName>
Element, das der lokalisierte Anzeigename ist, der den Benutzern angezeigt wird). Ersetzen Sie diecontoso_demo...
Dateinamen wie gewohnt durch die für Ihr Projekt geeigneten Namen, und (sehr wichtig) stellen Sie sicher, dass sich die.pfx
Datei nicht im aktuellen Verzeichnis befindet (andernfalls wäre sie als Teil Ihres Pakets erstellt worden, einschließlich des privaten Signaturschlüssels!):signtool sign /fd SHA256 /a /f ..\contoso_demo_key.pfx ..\contoso_demo.appx
Sie können
signtool sign /?
eingeben, um zu sehen, was jeder Parameter tut, aber kurz gefasst:/fd
Legt den Dateidigest-Algorithmus fest (SHA256 ist die Standardeinstellung für .appx)/a
Wählt automatisch das beste Signaturzertifikat aus./f
Gibt die Eingabedatei an, die das Signaturzertifikat enthält.
Schließlich können Sie nun auf die .appx
Datei doppelklicken, um sie zu installieren, oder wenn Sie die Befehlszeile bevorzugen, können Sie eine PowerShell-Eingabeaufforderung öffnen, zu dem Verzeichnis wechseln, das das Paket enthält, und geben Sie Folgendes ein (ersetzen Sie contoso_demo.appx
durch den Paketnamen):
add-appxpackage contoso_demo.appx
Wenn Sie Fehler darüber erhalten, dass das Zertifikat nicht vertrauenswürdig ist, stellen Sie sicher, dass es dem Computerspeicher (nicht dem Benutzerspeicher) hinzugefügt wird. Um das Zertifikat zum Computerspeicher hinzuzufügen, können Sie entweder die Befehlszeile oder den Windows-Explorer verwenden.
So verwenden Sie die Befehlszeile:
Führen Sie eine Visual Studio 2017- oder Visual Studio 2019-Eingabeaufforderung als Administrator aus.
Wechseln Sie zu dem Verzeichnis, das die
.cer
Datei enthält (denken Sie daran, dass diese außerhalb Ihrer Quell- oder Projektverzeichnisse liegt!)Geben Sie den folgenden Befehl ein, und ersetzen Sie
contoso_demo.cer
mit Ihrem Dateinamen:certutil -addstore TrustedPeople contoso_demo.cer
Sie können
certutil -addstore /?
ausführen, um zu sehen, was jeder Parameter tut, aber kurz gefasst:-addstore
Fügt dem Zertifikatsspeicher ein Zertifikat hinzu.TrustedPeople
Gibt den Speicher an, in dem das Zertifikat platziert wird.
Um Windows Explorer zu verwenden:
- Wechseln Sie zu dem Ordner, in dem die
.pfx
Datei enthalten ist. - Doppelklicken Sie auf
.pfx
Datei, und der Zertifikat-Import-Assistent sollte angezeigt werden. Local Machine
auswählen undNext
anklicken- Akzeptieren Sie die Benutzerkontosteuerungs-Administratorerweiterungsaufforderung, wenn sie angezeigt wird, und klicken Sie auf
Next
- Geben Sie das Kennwort für den privaten Schlüssel ein, falls vorhanden, und klicken Sie auf
Next
- Wählen Sie
Place all certificates in the following store
aus. - Klicken Sie auf
Browse
, und wählen Sie denTrusted People
Ordner (nicht „Vertrauenswürdige Herausgeber“) aus. Next
und dannFinish
anklicken
Nachdem Sie das Zertifikat zum Trusted People
Store hinzugefügt haben, versuchen Sie erneut, das Paket zu installieren.
Nun sollte Ihre App in der Liste „Alle Apps“ des Startmenüs mit den richtigen Informationen aus der .resw
/ .pri
Datei angezeigt werden. Wenn eine leere Zeichenkette oder die Zeichenkette ms-resource:...
angezeigt wird, ist ein Fehler aufgetreten. Überprüfen Sie die Bearbeitungen, und stellen Sie sicher, dass sie korrekt sind. Wenn Sie im Startmenü mit der rechten Maustaste auf Ihre App klicken, können Sie sie als Kachel anheften und überprüfen, ob dort auch die richtigen Informationen angezeigt werden.
Schritt 1.3: Hinzufügen weiterer unterstützter Sprachen
Nachdem die Änderungen am Paketmanifest vorgenommen wurden und die ursprüngliche resources.resw
Datei erstellt wurde, ist das Hinzufügen zusätzlicher Sprachen einfach.
Erstellen zusätzlicher lokalisierter Ressourcen
Erstellen Sie zunächst die zusätzlichen lokalisierten Ressourcenwerte.
Erstellen Sie im Strings
Ordner zusätzliche Ordner für jede Sprache, die Sie unterstützen, mithilfe des entsprechenden BCP-47-Codes (z.B Strings\de-DE
). Erstellen Sie in jedem dieser Ordner eine resources.resw
Datei (entweder mit einem XML-Editor oder dem Visual Studio-Designer), die die übersetzten Ressourcenwerte enthält. Es wird davon ausgegangen, dass Sie bereits über die lokalisierten Zeichenketten verfügen, und Sie müssen sie nur in die .resw
Datei kopieren. Dieses Dokument deckt nicht den Übersetzungsschritt selbst ab.
Die Strings\de-DE\resources.resw
Datei könnte z.B. wie folgt aussehen, wobei der hervorgehobene Text von en-US
geändert wurde:
<?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>
Bei den folgenden Schritten wird davon ausgegangen, dass Sie Ressourcen für beide de-DE
und fr-FR
hinzugefügt haben, aber dasselbe Muster kann für jede Sprache befolgt werden.
Aktualisieren Sie das Paketmanifest, um die unterstützten Sprachen aufzulisten
Das Paketmanifest muss aktualisiert werden, um die von der App unterstützten Sprachen auflisten zu können. Der Desktop App Converter fügt die Standardsprache hinzu, aber die anderen müssen explizit hinzugefügt werden. Wenn Sie die AppxManifest.xml
Datei direkt bearbeiten, aktualisieren Sie den Resources
Knoten wie folgt. Fügen Sie so viele Elemente hinzu, wie Sie benötigen, ersetzen Sie die von Ihnen unterstützten Sprachen und stellen Sie sicher, dass der erste Eintrag in der Liste die Standardsprache (Fallback) ist.
In diesem Beispiel ist Standard Englisch (USA) mit zusätzlicher Unterstützung für Deutsch (Deutschland) und Französisch (Frankreich):
<Resources>
<Resource Language="EN-US" />
<Resource Language="DE-DE" />
<Resource Language="FR-FR" />
</Resources>
Wenn Sie Visual Studio verwenden, sollten Sie nichts tun müssen. Wenn Sie sich Package.appxmanifest
ansehen, sollten Sie den speziellen X-Generate-Wert sehen, der den Build-Prozess veranlasst, die gefundenen Sprachen in Ihr Projekt einzufügen (basierend auf den Ordnern, die mit BCP-47-Codes benannt sind). Beachten Sie, dass dies kein gültiger Wert für ein echtes Paketmanifest ist; er funktioniert nur für Visual Studio-Projekte:
<Resources>
<Resource Language="x-generate" />
</Resources>
Neu erstellen mit den lokalisierten Werten
Jetzt können Sie Ihre Anwendung erneut erstellen und bereitstellen, und wenn Sie Ihre Spracheinstellungen in Windows ändern, sollten die neu lokalisierten Werte im Startmenü angezeigt werden (Anweisungen zum Ändern Ihrer Sprache finden Sie unten).
Für Visual Studio können Sie auch hier einfach Ctrl+Shift+B
zum Erstellen verwenden und auf das Projekt auf Deploy
mit der rechten Mausetaste anklicken.
Wenn Sie das Projekt manuell erstellen, führen Sie die gleichen Schritte wie oben aus, fügen aber beim Erstellen der Konfigurationsdatei die zusätzlichen Sprachen, getrennt durch Unterstriche, zur Liste der Standardqualifizierer (/dq
) hinzu. Um beispielsweise die im vorherigen Schritt hinzugefügten Ressourcen Englisch, Deutsch und Französisch zu unterstützen:
makepri createconfig /cf ..\contoso_demo.xml /dq en-US_de-DE_fr-FR /pv 10.0 /o
Dadurch wird eine PRI-Datei erstellt, die alle angegebenen Sprachen enthält, die Sie problemlos zum Testen verwenden können. Wenn die Gesamtgröße Ihrer Ressourcen gering ist oder Sie nur eine kleine Anzahl von Sprachen unterstützen, könnte dies für Ihre Versand-App akzeptabel sein. Nur wenn Sie die Vorteile der Minimierung der Installations-/Downloadgröße für Ihre Ressourcen nutzen möchten, müssen Sie sich die zusätzliche Arbeit machen, separate Sprachpakete zu erstellen.
Testen mit den lokalisierten Werten
Um die neuen lokalisierten Änderungen zu testen, fügen Sie einfach eine neue bevorzugte UI-Sprache zu Windows hinzu. Es ist nicht erforderlich, Sprachpakete herunterzuladen, das System neu zu starten oder die gesamte Windows-Benutzeroberfläche in einer Fremdsprache anzuzeigen.
- Ausführen der
Settings
-App (Windows + I
) - Gehen Sie zu
Time & language
- Gehen Sie zu
Region & language
- Klicken Sie auf
Add a language
. - Geben Sie die gewünschte Sprache ein (oder wählen Sie sie aus) (z.B
Deutsch
oderGerman
)
- Wenn Untersprachen vorhanden sind, wählen Sie die gewünschte Sprache aus (z.B
Deutsch / Deutschland
)
- Wählen Sie die neue Sprache aus der Sprachenliste aus.
- Klicken Sie auf
Set as default
.
Öffnen Sie nun das Startmenü und suchen Sie nach Ihrer Anwendung. Sie sollten die lokalisierten Werte für die gewählte Sprache sehen (andere Apps können ebenfalls lokalisiert erscheinen). Wenn der lokalisierte Name nicht sofort angezeigt wird, warten Sie einige Minuten, bis der Cache des Startmenüs aktualisiert wird. Um zu Ihrer Muttersprache zurückzukehren, machen Sie sie einfach zur Standardsprache in der Sprachenliste.
Schritt 1.4: Lokalisieren weiterer Teile des Paketmanifests (Option)
Andere Abschnitte des Paketmanifests können lokalisiert werden. Wenn Ihre Anwendung beispielsweise mit Dateierweiterungen arbeitet, sollte sie eine windows.fileTypeAssociation
Erweiterung im Manifest haben. Verwenden Sie den grün hervorgehobenen Text genau wie gezeigt (da er sich auf Ressourcen bezieht) und ersetzen Sie den gelb hervorgehobenen Text durch Informationen, die speziell für Ihre Anwendung gelten:
<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>
Sie können diese Informationen auch mithilfe des Visual Studio-Manifest-Designers mithilfe der Declarations
Registerkarte hinzufügen, wobei Sie die hervorgehobenen Werte notieren:
Fügen Sie nun den entsprechenden Ressourcennamen zu den einzelnen .resw
Dateien hinzu, und ersetzen Sie den hervorgehobenen Text durch den entsprechenden Text für Ihre App (denken Sie daran, dies für jede unterstützte Sprache zu tun!):
... existing content...
<data name="FileTypeDisplayName">
<value>Contoso Demo File</value>
</data>
<data name="FileTypeInfoTip">
<value>Files used by Contoso Demo App</value>
</data>
Dies wird dann in Teilen der Windows-Shell angezeigt, wie z.B. Explorer:
Erstellen und testen Sie das Paket wie zuvor, und führen Sie alle neuen Szenarien aus, in denen die neuen UI-Zeichenketten angezeigt werden sollen.
Phase 2: Verwenden von MRT zum Identifizieren und Suchen von Ressourcen
Im vorherigen Abschnitt wurde gezeigt, wie Sie MRT verwenden, um die Manifestdatei Ihrer App zu lokalisieren, damit die Windows-Shell den Namen und andere Metadaten der App korrekt anzeigen kann. Hierfür waren keine Codeänderungen erforderlich; es erforderte einfach die Verwendung von .resw
Dateien und einigen zusätzlichen Tools. In diesem Abschnitt wird gezeigt, wie Sie MRT verwenden, um Ressourcen in Ihren vorhandenen Ressourcenformaten zu suchen und den vorhandenen Ressourcenbehandlungscode mit minimalen Änderungen zu verwenden.
Annahmen zu vorhandenem Dateilayout und Anwendungscode
Da es viele Möglichkeiten zum Lokalisieren von Win32-Desktop-Apps gibt, macht dieses Dokument einige vereinfachende Annahmen über die Struktur der vorhandenen Anwendung, die Sie ihrer spezifischen Umgebung zuordnen müssen. Möglicherweise müssen Sie einige Änderungen an Ihrem vorhandenen Codebasis- oder Ressourcenlayout vornehmen, um den Anforderungen von MRT zu entsprechen, und diese sind weitgehend außerhalb des Umfangs für dieses Dokument.
Layout Ressourcendatei
In diesem Artikel wird davon ausgegangen, dass ihre lokalisierten Ressourcen alle über dieselben Dateinamen verfügen (z.B. contoso_demo.exe.mui
oder contoso_strings.dll
oder contoso.strings.xml
) aber in verschiedenen Ordnern mit BCP-47-Namen (en-US
, de-DE
usw.) platziert wurden. Es spielt keine Rolle, wie viele Ressourcendateien Sie haben, wie diese heißen, welche Dateiformate / zugehörige APIs sie haben usw. Das Einzige, was zählt, ist, dass jede logische Ressource denselben Dateinamen hat (aber in einem anderen physischen Verzeichnis liegt).
Ein Gegenbeispiel: Wenn Ihre Anwendung eine flache Dateistruktur mit einem einzigen Resources
Verzeichnis verwendet, das die Dateien english_strings.dll
und french_strings.dll
enthält, würde sie nicht gut auf MRT abgebildet werden. Eine bessere Struktur wäre ein Resources
Verzeichnis mit Unterverzeichnissen und Dateien en\strings.dll
und fr\strings.dll
. Es ist auch möglich, denselben Basisdateinamen zu verwenden, aber mit eingebetteten Qualifizierern, wie strings.lang-en.dll
und strings.lang-fr.dll
, aber die Verwendung von Verzeichnissen mit den Sprachcodes ist konzeptionell einfacher, sodass wir uns darauf konzentrieren werden.
Hinweis
Es ist weiterhin möglich, MRT und die Vorteile der Verpackung zu verwenden, auch wenn Sie dieser Datei-Namenskonvention nicht folgen können; es erfordert nur mehr Arbeit.
Die Anwendung kann z.B. eine Reihe von benutzerdefinierten UI-Befehlen (für Schaltflächenbeschriftungen usw.) in einer einfachen Textdatei mit dem Namen ui.txt haben, die unter einem UICommands-Ordner angeordnet ist:
+ ProjectRoot |--+ Strings | |--+ en-US | | \--- resources.resw | \--+ de-DE | \--- resources.resw |--+ UICommands | |--+ en-US | | \--- ui.txt | \--+ de-DE | \--- ui.txt |--- AppxManifest.xml |--- ...rest of project...
Ressourcen-Ladecode
In diesem Artikel wird davon ausgegangen, dass Sie an einem bestimmten Punkt n Ihrem Code die Datei suchen möchten, die eine lokalisierte Ressource enthält, diese laden und dann verwenden möchten. Die zum Laden der Ressourcen verwendeten APIs, die zum Extrahieren der Ressourcen verwendeten APIs usw. sind nicht wichtig. In Pseudocode gibt es im Wesentlichen drei Schritte:
set userLanguage = GetUsersPreferredLanguage() set resourceFile = FindResourceFileForLanguage(MY_RESOURCE_NAME, userLanguage) set resource = LoadResource(resourceFile) // now use 'resource' however you want
MRT erfordert nur das Ändern der ersten beiden Schritte in diesem Prozess – wie Sie die besten Kandidaten-Ressourcen bestimmen und wie Sie sie finden. Es ist nicht erforderlich, die Art und Weise zu ändern, wie Sie die Ressourcen laden oder verwenden (es bietet jedoch Möglichkeiten, dies zu tun, wenn Sie sie nutzen möchten).
Die Anwendung kann z.B. die Win32-API, GetUserPreferredUILanguages
die CRT-Funktion sprintf
und die Win32-API CreateFile
verwenden, um die drei oben genannten Pseudocodefunktionen zu ersetzen. Analysieren Sie dann die Textdatei, die nach name=value
Paaren sucht. (Die Details sind nicht wichtig; dies soll lediglich verdeutlichen, dass MRT keinen Einfluss auf die Techniken hat, mit denen Ressourcen behandelt werden, sobald sie gefunden wurden).
Schritt 2.1: Codeänderungen zur Verwendung von MRT zum Suchen von Dateien
Das Wechseln ihres Codes für die Verwendung von MRT zum Auffinden von Ressourcen ist nicht schwierig. Es erfordert eine Handvoll WinRT-Typen und einige Codezeilen. Die Standard Typen, die Sie verwenden werden, sind wie folgt:
- ResourceContext, der den derzeit aktiven Satz von Kennzeichnerwerten (Sprache, Skalierungsfaktor, usw.) kapselt
- ResourceManager (die WinRT-Version, nicht die .NET-Version), die den Zugriff auf alle Ressourcen aus der PRI-Datei ermöglicht
- ResourceMap, die eine bestimmte Teilmenge der Ressourcen in der PRI-Datei darstellt (in diesem Beispiel die dateibasierten Ressourcen im Vergleich zu den Zeichenketten-Ressourcen)
- NamedResource, die eine logische Ressource und alle möglichen Kandidaten darstellt
- ResourceCandidate, die eine einzelne konkrete Kandidatenressource darstellt
Im Pseudocode lautet die Art und Weise, wie Sie einen bestimmten Ressourcen-Dateinamen (wie UICommands\ui.txt
im Beispiel oben) auflösen würden:
// 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
Beachten Sie insbesondere, dass der Code keinen bestimmten Sprachordner anfordert - wie z.B. UICommands\en-US\ui.txt
-, obwohl die Dateien auf dem Datenträger vorhanden sind. Stattdessen fragt es nach dem logischen Dateinamen UICommands\ui.txt
und verlässt sich darauf, dass MRT die entsprechende Datei auf dem Datenträger in einem der Sprachverzeichnisse findet.
Von hier aus könnte die Beispielanwendung weiterhin die CreateFile
verwenden, um die absoluteFileName
zu laden und die name=value
Paare zu parsen, genau wie zuvor; keine dieser Logiken muss in der Anwendung geändert werden. Wenn Sie in C# oder C++/CX schreiben, ist der eigentliche Code nicht viel komplizierter als dies (und tatsächlich können viele der Zwischenvariablen entfernt werden) – siehe Abschnitt zum Laden von .NET-Ressourcen unten. C++/WRL-basierte Anwendungen sind aufgrund der COM-basierten Low-Level-APIs, die zum Aktivieren und Aufrufen der WinRT-APIs verwendet werden, komplexer, aber die grundlegenden Schritte, die Sie unternehmen, sind dieselben - siehe den Abschnitt über das Laden von Win32 MUI-Ressourcen weiter unten.
Laden von .NET-Ressourcen
Da .NET über einen eingebauten Mechanismus zum Auffinden und Laden von Ressourcen verfügt (bekannt als „Satellite Assemblies“), muss kein expliziter Code ersetzt werden, wie im obigen synthetischen Beispiel - in .NET brauchen Sie nur Ihre Ressourcen-DLLs in den entsprechenden Verzeichnissen und sie werden automatisch für Sie gefunden. Wenn eine Anwendung mit Hilfe von Ressourcenpaketen als MSIX oder .appx verpackt wird, ist die Verzeichnisstruktur etwas anders - statt dass die Ressourcenverzeichnisse Unterverzeichnisse des Hauptanwendungsverzeichnisses sind, sind sie gleichrangig mit diesem (oder gar nicht vorhanden, wenn der Benutzer die Sprache nicht in seinen Einstellungen festgelegt hat).
Stellen Sie sich beispielsweise eine .NET-Anwendung mit dem folgenden Layout vor, in der alle Dateien unter dem MainApp
Ordner vorhanden sind:
+ MainApp |--+ en-us | \--- MainApp.resources.dll |--+ de-de | \--- MainApp.resources.dll |--+ fr-fr | \--- MainApp.resources.dll \--- MainApp.exe
Nach der Konvertierung in .appx sieht das Layout etwa so aus, vorausgesetzt, en-US
war die Standardsprache und der Benutzer hat sowohl Deutsch als auch Französisch in seiner Sprachliste:
+ 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
Da die lokalisierten Ressourcen nicht mehr in Unterverzeichnissen unterhalb des Installationsverzeichnisses der ausführbaren Hauptdatei vorhanden sind, schlägt die integrierte .NET-Ressourcenauflösung fehl. Glücklicherweise verfügt .NET über einen gut definierten Mechanismus für die Behandlung fehlgeschlagener Assembly-Ladeversuche – das AssemblyResolve
Ereignis. Eine .NET-App mit MRT muss sich für dieses Ereignis registrieren und die fehlende Assembly für das .NET-Ressourcensubsystem bereitstellen.
Im Folgenden finden Sie ein präziseres Beispiel für die Verwendung der WinRT-APIs zum Auffinden von Satelliten-Assemblies, die von .NET verwendet werden. Der Code ist absichtlich komprimiert, um eine minimale Implementierung zu zeigen, obwohl Sie sehen können, dass er sich eng an den obigen Pseudocode anlehnt, wobei die übergebene ResolveEventArgs
den Namen der Assembly angibt, die wir finden müssen. Eine lauffähige Version dieses Codes (mit detaillierten Kommentaren und Fehlerbehandlung) finden Sie in der Datei PriResourceRsolver.cs
im .NET Assembly Resolver-Beispiel auf 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);
}
}
Anhand der obigen Klasse würden Sie das Folgende zu einem frühen Zeitpunkt in den Startcode Ihrer Anwendung einfügen (bevor irgendwelche lokalisierten Ressourcen geladen werden müssen):
void EnableMrtResourceLookup()
{
AppDomain.CurrentDomain.AssemblyResolve += PriResourceResolver.ResolveResourceDll;
}
Die .NET-Laufzeitumgebung löst das AssemblyResolve
Ereignis immer dann aus, wenn sie die Ressourcen-DLLs nicht finden kann. Zu diesem Zeitpunkt findet der bereitgestellte Event-Handler die gewünschte Datei über MRT und gibt die Assembly zurück.
Hinweis
Wenn Ihre Anwendung bereits über einen AssemblyResolve
Handler für andere Zwecke verfügt, müssen Sie den Code zur Ressourcenauflösung in Ihren bestehenden Code integrieren.
Laden von Win32 MUI-Ressourcen
Das Laden von Win32-MUI-Ressourcen ist im Wesentlichen identisch mit dem Laden von .NET-Satellitenassemblys, aber stattdessen mit C++/CX- oder C++/WRL-Code. Die Verwendung von C++/CX ermöglicht einen viel einfacheren Code, der dem obigen C#-Code sehr ähnlich ist. Allerdings werden dabei C++-Spracherweiterungen, Compiler-Switches und zusätzliche Laufzeitüberlagerungen verwendet, die Sie vielleicht vermeiden möchten. Wenn das der Fall ist, bietet die Verwendung von C++/WRL eine viel weniger aufwändige Lösung, die allerdings einen ausführlicheren Code erfordert. Wenn Sie jedoch mit der ATL-Programmierung (oder COM im Allgemeinen) vertraut sind, sollte Ihnen WRL vertraut vorkommen.
Die folgende Beispielfunktion zeigt, wie Sie C++/WRL verwenden, um eine bestimmte Ressourcen-DLL zu laden und eine HINSTANCE
zurückzugeben, die verwendet werden kann, um weitere Ressourcen mithilfe der üblichen Win32-Ressourcen-APIs zu laden. Beachten Sie, dass dieser Code im Gegensatz zum C#-Beispiel, bei dem die ResourceContext
explizit mit der von der .NET-Laufzeit angeforderten Sprache initialisiert wird, auf die aktuelle Sprache des Benutzers angewiesen ist.
#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: Erstellen von Ressourcenpaketen
Nachdem Sie nun über ein „Fat Pack“ verfügen, das alle Ressourcen enthält, gibt es zwei Pfade zum Erstellen separater Standard Paket- und Ressourcenpakete, um Download- und Installationsgrößen zu minimieren:
- Verwenden Sie ein vorhandenes Fat Pack, und führen Sie es über das Bundle-Generator-Tool aus, um automatisch Ressourcenpakete zu erstellen. Dies ist der bevorzugte Ansatz, wenn Sie ein Build-System haben, das bereits ein Fat Pack erzeugt und Sie es nachbearbeiten möchten, um die Ressourcenpakete zu erzeugen.
- Erstellen Sie die einzelnen Ressourcenpakete direkt und fügen Sie sie zu einem Bündel zusammen. Dies ist der bevorzugte Ansatz, wenn Sie mehr Kontrolle über Ihr Buildsystem haben und die Pakete direkt erstellen können.
Schritt 3.1: Erstellen des Bündels
Verwenden des Bundle-Generator-Tools
Um das Bundle-Generator-Tool zu verwenden, muss die für das Paket erstellte PRI-Konfigurationsdatei manuell aktualisiert werden, um den <packaging>
Abschnitt zu entfernen.
Wenn Sie Visual Studio verwenden, lesen Sie Sicherstellen, dass Ressourcen auf einem Gerät installiert werden, unabhängig davon, ob ein Gerät sie benötigt, um zu erfahren, wie Sie alle Sprachen in das Hauptpaket einbauen, indem Sie die Dateien priconfig.packaging.xml
und priconfig.default.xml
erstellen.
Wenn Sie Dateien manuell bearbeiten, führen Sie die folgenden Schritte aus:
Erstellen Sie die Konfigurationsdatei auf die gleiche Weise wie zuvor, und ersetzen Sie dabei den richtigen Pfad, Dateinamen und Sprachen:
makepri createconfig /cf ..\contoso_demo.xml /dq en-US_de-DE_es-MX /pv 10.0 /o
Öffnen Sie die erstellte
.xml
Datei manuell, und löschen Sie den gesamten<packaging&rt;
Abschnitt (behalten Sie jedoch alles andere intakt):<?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> ... ...
Erstellen Sie die
.pri
Datei und das.appx
Paket wie zuvor mit der aktualisierten Konfigurationsdatei und den entsprechenden Verzeichnis- und Dateinamen (weitere Informationen zu diesen Befehlen finden Sie oben):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
Nachdem das Paket erstellt wurde, verwenden Sie den folgenden Befehl, um das Bündel mit den entsprechenden Verzeichnis- und Dateinamen zu erstellen:
BundleGenerator.exe -Package ..\contoso_demo.appx -Destination ..\bundle -BundleName contoso_demo
Jetzt können Sie zum letzten Schritt übergehen und signieren (siehe unten).
Manuelles Erstellen von Ressourcenpaketen
Für das manuelle Erstellen von Ressourcenpaketen ist es erforderlich, einen etwas anderen Satz von Befehlen auszuführen, um separate .pri
und .appx
Dateien zu erstellen. Diese sind alle ähnlich wie die oben verwendeten Befehle zum Erstellen von Fettpaketen, sodass eine minimale Erklärung gegeben wird. Hinweis: Alle Befehle gehen davon aus, dass das aktuelle Verzeichnis das Verzeichnis ist, das die AppXManifest.xml
Datei enthält, aber alle Dateien werden in das übergeordnete Verzeichnis eingefügt (Sie können bei Bedarf ein anderes Verzeichnis verwenden, aber Sie sollten das Projektverzeichnis nicht mit einer dieser Dateien belasten). Ersetzen Sie wie immer die Dateinamen „Contoso“ durch Ihre eigenen Dateinamen.
Verwenden Sie den folgenden Befehl, um eine Konfigurationsdatei zu erstellen, die nur die Standardsprache als Standardqualifizierer benennt - in diesem Fall
en-US
:makepri createconfig /cf ..\contoso_demo.xml /dq en-US /pv 10.0 /o
Erstellen Sie eine Standard
.pri
und.map.txt
Datei für das Standard-Paket sowie einen zusätzlichen Satz von Dateien für jede Sprache in Ihrem Projekt mit dem folgenden Befehl:makepri new /pr . /cf ..\contoso_demo.xml /of ..\resources.pri /mf AppX /o
Verwenden Sie den folgenden Befehl, um das Standard-Paket zu erstellen (das den ausführbaren Code und Standardsprachen-Ressourcen enthält). Ändern Sie wie immer den Namen entsprechend, obwohl Sie das Paket in einem separaten Verzeichnis ablegen sollten, um das Erstellen des Bündels später zu vereinfachen (in diesem Beispiel wird das
..\bundle
Verzeichnis verwendet):makeappx pack /m .\AppXManifest.xml /f ..\resources.map.txt /p ..\bundle\contoso_demo.main.appx /o
Nachdem das Standard Paket erstellt wurde, verwenden Sie den folgenden Befehl einmal für jede zusätzliche Sprache (d.h. wiederholen Sie diesen Befehl für jede im vorherigen Schritt generierte Sprachzuordnungsdatei). Auch hier sollte sich die Ausgabe in einem separaten Verzeichnis befinden (dasselbe wie das Standard-Paket). Beachten Sie, dass die Sprache sowohl in der
/f
Option als auch in der/p
Option und die Verwendung des neuen/r
Arguments angegeben ist (das angibt, dass ein Ressourcenpaket gewünscht ist):makeappx pack /r /m .\AppXManifest.xml /f ..\resources.language-de.map.txt /p ..\bundle\contoso_demo.de.appx /o
Kombinieren Sie alle Pakete aus dem Bündelverzeichnis in einer einzigen
.appxbundle
Datei. Die neue/d
Option gibt das Verzeichnis an, das für alle Dateien im Bündel verwendet werden soll (aus diesem Grund werden die.appx
Dateien im vorherigen Schritt in ein separates Verzeichnis eingefügt):makeappx bundle /d ..\bundle /p ..\contoso_demo.appxbundle /o
Der letzte Schritt zum Erstellen des Pakets besteht darin, das Paket zu signieren.
Schritt 3.2: Signieren des Bündels
Nachdem Sie die .appxbundle
Datei erstellt haben (entweder über das Bundle-Generator-Tool oder manuell), verfügen Sie über eine einzelne Datei, die das Standard Paket sowie alle Ressourcenpakete enthält. Der letzte Schritt besteht darin, die Datei zu signieren, damit Windows sie installiert:
signtool sign /fd SHA256 /a /f ..\contoso_demo_key.pfx ..\contoso_demo.appxbundle
Dadurch wird eine signierte .appxbundle
Datei erstellt, die das Standard-Paket sowie alle sprachspezifischen Ressourcenpakete enthält. Es kann wie eine Paketdatei doppelt geklickt werden, um die App sowie alle geeigneten Sprachen basierend auf den Windows-Spracheinstellungen des Benutzers zu installieren.