Erstellen von Ressourcendateien für .NET-Apps

Sie können Ressourcen (z. B. Zeichenfolgen, Bilder oder Objektdaten) in Ressourcendateien einschließen, um sie für die Anwendung leicht verfügbar zu machen. .NET Framework bietet fünf Möglichkeiten, Ressourcendateien zu erstellen:

  • Erstellen Sie eine Textdatei, die Zeichenfolgenressourcen enthält. Sie können die Textdatei mithilfe des Resource File Generator (Resgen.exe) in eine binäre Ressourcendatei (RESOURCES-Datei) konvertieren. Anschließend können Sie die binäre Ressourcendatei mit einem Sprachcompiler in eine ausführbare Datei der Anwendung oder eine Anwendungsbibliothek einbetten, oder Sie können sie mithilfe des Assembly Linker (Al.exe) in eine Satellitenassembly einbetten. Weitere Informationen finden Sie im Abschnitt Ressourcen in Textdateien.

  • Erstellen Sie eine XML-Ressourcendatei (.resx), die Zeichenfolgen-, Bild- oder Objektdaten enthält. Sie können die RESX-Datei mithilfe des Resource File Generator (Resgen.exe) in eine binäre Ressourcendatei (RESOURCES-Datei) konvertieren. Anschließend können Sie die binäre Ressourcendatei mit einem Sprachcompiler in eine ausführbare Datei der Anwendung oder eine Anwendungsbibliothek einbetten, oder Sie können sie mithilfe des Assembly Linker (Al.exe) in eine Satellitenassembly einbetten. Weitere Informationen finden Sie im Abschnitt Ressourcen in RESX-Dateien.

  • Erstellen Sie programmgesteuert mithilfe von Typen im System.Resources-Namespace eine XML-Ressourcendatei (.resx). Sie können eine RESX-Datei erstellen, ihre Ressourcen auflisten und bestimmte Ressourcen nach dem Namen abrufen. Weitere Informationen finden Sie unter Programmgesteuertes Arbeiten mit RESX-Dateien.

  • Erstellen Sie programmgesteuert eine binäre Ressourcendatei (.resources). Anschließend können Sie die Datei mit einem Sprachcompiler in eine ausführbare Datei der Anwendung oder eine Anwendungsbibliothek einbetten, oder Sie können sie mithilfe des Assembly Linker (Al.exe) in eine Satellitenassembly einbetten. Weitere Informationen finden Sie im Abschnitt Ressourcen in RESOURCES-Dateien.

  • Verwenden Sie Visual Studio, um eine Ressourcendatei zu erstellen und in das Projekt einzuschließen. Visual Studio stellt einen Ressourcen-Editor bereit, mit dem Sie Ressourcen hinzufügen, löschen und ändern können. Zur Kompilierzeit wird die Ressourcendatei automatisch in eine binäre RESOURCES-Datei konvertiert und in eine Anwendungsassembly oder eine Satellitenassembly eingebettet. Weitere Informationen finden Sie im Abschnitt Ressourcendateien in Visual Studio.

Ressourcen in Textdateien

Sie können Textdateien (TXT oder RESTEXT) verwenden, um nur Zeichenfolgenressourcen zu speichern. Verwenden Sie für Nicht-Zeichenfolgenressourcen RESX-Dateien, oder erstellen Sie sie programmgesteuert. Textdateien, die Zeichenfolgenressourcen enthalten, haben das folgende Format:

# This is an optional comment.
name = value

; This is another optional comment.
name = value

; The following supports conditional compilation if X is defined.
#ifdef X
name1=value1
name2=value2
#endif

# The following supports conditional compilation if Y is undefined.
#if !Y
name1=value1
name2=value2
#endif

Das Ressourcendateiformat von .txt und von .restext-Dateien ist identisch. Die .restext-Dateierweiterung dient lediglich dazu, Textdateien direkt als textbasierte Ressourcendateien identifizierbar zu machen.

Zeichenfolgenressourcen werden als Name/Wert-Paare (name/value pairs) angezeigt, wobei name eine Zeichenfolge ist, die die Ressource identifiziert, und value die Ressourcenzeichenfolge, die zurückgegeben wird, wenn Sie name an eine Ressourcenabrufmethode wie ResourceManager.GetString übergeben. name und value müssen durch ein Gleichheitszeichen (=) getrennt werden. Beispiel:

FileMenuName=File
EditMenuName=Edit
ViewMenuName=View
HelpMenuName=Help

Achtung

Verwenden Sie Ressourcendateien nicht, um Kennwörter, sicherheitsrelevante Informationen oder private Daten zu speichern.

Leere Zeichenfolgen (eine Ressource, deren Wert String.Empty ist) sind in Textdateien zulässig. Zum Beispiel:

EmptyString=

Ab NET Framework 4.5 und in allen Versionen von .NET Core unterstützen Textdateien die bedingte Kompilierung mit den Konstrukten #ifdefSymbol... #endif und #if !Symbol... #endif. Sie können dann den /define-Schalter mit dem Resource File Generator (Resgen.exe) verwenden, um Symbole zu definieren. Jede Ressource erfordert ein eigenes Konstrukt, entweder #ifdefSymbol... #endif oder #if !Symbol... #endif. Wenn Sie eine #ifdef-Anweisung verwenden und Symbol definiert ist, wird die zugeordnete Ressource in die RESOURCES-Datei einbezogen; andernfalls wird sie nicht eingeschlossen. Wenn Sie eine #if !-Anweisung verwenden und Symbol nicht definiert ist, wird die zugeordnete Ressource in die RESOURCES-Datei einbezogen; andernfalls wird sie nicht eingeschlossen.

Kommentare sind in Textdateien optional, und am Anfang einer Zeile wird entweder ein Semikolon (;) vorangestellt oder ein Nummernzeichen (#). Zeilen, die Kommentare enthalten sind, können an beliebiger Stelle in der Datei eingefügt werden. Kommentare sind nicht in einer mit dem Resource File Generator (Resgen.exe) erstellten kompilierten RESOURCES-Datei enthalten.

Alle leeren Zeilen in den Textdateien werden als Leerzeichen angesehen ignoriert.

Im folgenden Beispiel werden zwei Zeichenfolgenressourcen mit dem Namen OKButton und CancelButton definiert.

#Define resources for buttons in the user interface.
OKButton=OK
CancelButton=Cancel

Wenn die Textdatei doppelte Vorkommen von name enthält, zeigt der Resource File Generator (Resgen.exe) eine Warnung an und ignoriert den zweiten Namen.

value darf keine Zeilenvorschubzeichen enthalten. Sie können aber Escapezeichen im C-Stil verwenden, z. B. \n für eine neue Zeile oder \t für einen Tabstopp. Sie können einen umgekehrten Schrägstrich verwenden, wenn er mit Escapezeichen versehen wird (beispielsweise „\\“). Darüber hinaus ist eine leere Zeichenfolge zulässig.

Sie können Ressourcen im Textdateiformat mit der UTF-8- oder der UTF-16-Codierung entweder in einer Little-Endian- oder einer Big-Endian-Bytereihenfolge speichern. Obwohl der Resource File Generator (Resgen.exe) TXT-Dateien in RESOURCES-Dateien konvertiert, behandelt er Dateien standardmäßig als UTF-8. Wenn "Resgen.exe" eine als UTF-16 codierte Datei erkennen soll, müssen Sie am Anfang der Datei eine Unicode-Bytereihenfolgemarkierung (U+FEFF) angeben.

Um eine Ressourcendatei im Textformat in eine .NET-Assembly einzubetten, müssen Sie die Datei mit dem Resource File Generator (Resgen.exe) in eine binäre Ressourcendatei (RESOURCES-Datei) konvertieren. Sie können die RESOURCES-Datei dann mit einem Sprachcompiler in eine .NET-Assembly oder mit dem Assembly Linker (Al.exe) in eine Satellitenassembly einbetten.

Im folgenden Beispiel wird eine Ressourcendatei im Textformat mit dem Namen "GreetingResources.txt" für eine einfache Konsolenanwendung "Hello World" verwendet. Die Textdatei definiert zwei Zeichenfolgen, prompt und greeting, die den Benutzer zur Eingabe seines Namens auffordern und einen Gruß anzeigen.

# GreetingResources.txt
# A resource file in text format for a "Hello World" application.
#
# Initial prompt to the user.
prompt=Enter your name:
# Format string to display the result.
greeting=Hello, {0}!

Die Textdatei wird mit dem folgenden Befehl in eine RESOURCES-Datei konvertiert:

resgen GreetingResources.txt

Im folgenden Beispiel wird der Quellcode für eine Konsolenanwendung veranschaulicht, die dem Benutzer mithilfe der RESOURCES-Datei Nachrichten anzeigt.

using System;
using System.Reflection;
using System.Resources;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("GreetingResources",
                               typeof(Example).Assembly);
      Console.Write(rm.GetString("prompt"));
      string name = Console.ReadLine();
      Console.WriteLine(rm.GetString("greeting"), name);
   }
}
// The example displays output like the following:
//       Enter your name: Wilberforce
//       Hello, Wilberforce!
Imports System.Reflection
Imports System.Resources

Module Example
    Public Sub Main()
        Dim rm As New ResourceManager("GreetingResources",
                                      GetType(Example).Assembly())
        Console.Write(rm.GetString("prompt"))
        Dim name As String = Console.ReadLine()
        Console.WriteLine(rm.GetString("greeting"), name)
    End Sub
End Module
' The example displays output like the following:
'       Enter your name: Wilberforce
'       Hello, Wilberforce!

Wenn Sie Visual Basic verwenden und die Quellcodedatei "Greeting.vb" genannt wird, erstellt der folgende Befehl eine ausführbare Datei, die die eingebettete RESOURCES-Datei einschließt:

vbc greeting.vb -resource:GreetingResources.resources

Wenn Sie C# verwenden und die Quellcodedatei "Greeting.cs" genannt wird, erstellt der folgende Befehl eine ausführbare Datei, die die eingebettete RESOURCES-Datei einschließt:

csc greeting.cs -resource:GreetingResources.resources

Ressourcen in RESX-Dateien

Im Gegensatz zu Textdateien, in denen nur Zeichenfolgenressourcen gespeichert werden können, können in XML-Ressourcendateien (.resx) Zeichenfolgen, Binärdaten wie Bilder, Symbole und Audioclips sowie programmgesteuerte Objekte gespeichert werden. Eine RESX-Datei enthält einen Standardheader, der das Format der Ressourceneinträge beschreibt und die XML-Versioninginformationen zum Interpretieren der Daten angibt. Die Ressourcendateidaten folgen auf den XML-Header. Jedes Datenelement besteht aus einem Name-Wert-Paar, das in einem data-Tag enthalten ist. Sein name-Attribut definiert den Ressourcennamen, und das geschachtelte value-Tag enthält den Ressourcenwert. Bei Zeichenfolgendaten enthält das value-Tag die Zeichenfolge.

Das folgende data-Tag definiert z. B. eine Zeichenfolgenressource mit dem Namen von prompt, deren Wert "Enter your name:" lautet.

<data name="prompt" xml:space="preserve">
  <value>Enter your name:</value>
</data>

Achtung

Verwenden Sie Ressourcendateien nicht, um Kennwörter, sicherheitsrelevante Informationen oder private Daten zu speichern.

Bei Ressourcenobjekten enthält das Tag data ein type-Attribut, das den Datentyp der Ressource angibt. Bei Objekten, die aus Binärdaten bestehen, schließt das data-Tag auch ein mimetype-Attribut ein, das den base64-Typ der Binärdaten angibt.

Hinweis

Alle RESX-Dateien verwenden ein Programm für die binäre Serialisierung, um die Binärdaten für einen bestimmten Typ zu generieren und zu analysieren. Daher kann eine RESX-Datei ungültig werden, wenn das Format für die binäre Serialisierung für ein Objekt auf nicht kompatible Weise geändert wird.

Im folgenden Beispiel wird ein Teil einer RESX-Datei veranschaulicht, die eine Int32-Ressource und ein Bitmapbild enthält.

<data name="i1" type="System.Int32, mscorlib">
  <value>20</value>
</data>

<data name="flag" type="System.Drawing.Bitmap, System.Drawing,
    Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    mimetype="application/x-microsoft.net.object.bytearray.base64">
  <value>
    AAEAAAD/////AQAAAAAAAAAMAgAAADtTeX…
  </value>
</data>

Wichtig

Da RESX-Dateien aus wohlgeformtem XML in einem vordefinierten Format bestehen müssen, empfiehlt es sich nicht, mit RESX-Dateien manuell zu arbeiten, insbesondere, wenn die RESX-Dateien andere Ressourcen als Zeichenfolgen enthalten. Stattdessen bietet Visual Studio eine transparente Schnittstelle zum Erstellen und Bearbeiten von RESX-Dateien. Weitere Informationen finden Sie im Abschnitt Ressourcendateien in Visual Studio. Sie können RESX-Dateien auch programmgesteuert erstellen und bearbeiten. Weitere Informationen finden Sie unter Programmgesteuertes Arbeiten mit RESX-Dateien.

Ressourcen in RESOURCES-Dateien

Mit der System.Resources.ResourceWriter-Klasse können Sie eine binäre Ressourcendatei (.resources) direkt aus Code programmgesteuert erstellen. Sie können auch mithilfe des Resource File Generator (Resgen.exe) eine RESOURCES-Datei aus einer Textdatei oder einer RESX-Datei erstellen. Die RESOURCES-Datei kann neben Zeichenfolgendaten Binärdaten (Bytearrays) und Objektdaten enthalten. Das programmgesteuerte Erstellen einer RESOURCES-Datei erfordert die folgenden Schritte:

  1. Erstellen Sie ein ResourceWriter-Objekt mit einem eindeutigen Dateinamen. Geben Sie dazu entweder einen Dateinamen oder einen Dateistream zu einem ResourceWriter-Klassenkonstruktor an.

  2. Rufen Sie eine der Überladungen der ResourceWriter.AddResource-Methode für jede benannte Ressource an, die der Datei hinzugefügt werden soll. Die Ressource kann eine Zeichenfolge, ein Objekt oder eine Auflistung der Binärdaten (ein Bytearray) sein.

  3. Rufen Sie die ResourceWriter.Close-Methode auf, um die Ressourcen in die Datei zu schreiben und das ResourceWriter-Objekt zu schließen.

Achtung

Verwenden Sie Ressourcendateien nicht, um Kennwörter, sicherheitsrelevante Informationen oder private Daten zu speichern.

Im folgenden Beispiel wird programmgesteuert eine RESOURCES-Datei mit dem Namen "CarResources.resources" erstellt, mit der sechs Zeichenfolgen, ein Symbol und zwei anwendungsdefinierte Objekte (zwei Automobile-Objekte) gespeichert werden. Die im Beispiel definierte und instanziierte Klasse Automobile wird mit dem Attribut SerializableAttribute markiert, wodurch die Klasse vom binären Serialisierungsformatierer beibehalten werden kann.

using System;
using System.Drawing;
using System.Resources;

[Serializable()] public class Automobile
{
   private string carMake;
   private string carModel;
   private int carYear;
   private int carDoors;
   private int carCylinders;

   public Automobile(string make, string model, int year) :
                     this(make, model, year, 0, 0)
   { }

   public Automobile(string make, string model, int year,
                     int doors, int cylinders)
   {
      this.carMake = make;
      this.carModel = model;
      this.carYear = year;
      this.carDoors = doors;
      this.carCylinders = cylinders;
   }

   public string Make {
      get { return this.carMake; }
   }

   public string Model {
      get { return this.carModel; }
   }

   public int Year {
      get { return this.carYear; }
   }

   public int Doors {
      get {
         return this.carDoors; }
   }

   public int Cylinders {
      get {
         return this.carCylinders; }
   }
}

public class Example
{
   public static void Main()
   {
      // Instantiate an Automobile object.
      Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4);
      Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4);
      // Define a resource file named CarResources.resx.
      using (ResourceWriter rw = new ResourceWriter(@".\CarResources.resources"))
      {
         rw.AddResource("Title", "Classic American Cars");
         rw.AddResource("HeaderString1", "Make");
         rw.AddResource("HeaderString2", "Model");
         rw.AddResource("HeaderString3", "Year");
         rw.AddResource("HeaderString4", "Doors");
         rw.AddResource("HeaderString5", "Cylinders");
         rw.AddResource("Information", SystemIcons.Information);
         rw.AddResource("EarlyAuto1", car1);
         rw.AddResource("EarlyAuto2", car2);
      }
   }
}
Imports System.Drawing
Imports System.Resources

<Serializable()> Public Class Automobile
    Private carMake As String
    Private carModel As String
    Private carYear As Integer
    Private carDoors AS Integer
    Private carCylinders As Integer

    Public Sub New(make As String, model As String, year As Integer)
        Me.New(make, model, year, 0, 0)
    End Sub

    Public Sub New(make As String, model As String, year As Integer,
                   doors As Integer, cylinders As Integer)
        Me.carMake = make
        Me.carModel = model
        Me.carYear = year
        Me.carDoors = doors
        Me.carCylinders = cylinders
    End Sub

    Public ReadOnly Property Make As String
        Get
            Return Me.carMake
        End Get
    End Property

    Public ReadOnly Property Model As String
        Get
            Return Me.carModel
        End Get
    End Property

    Public ReadOnly Property Year As Integer
        Get
            Return Me.carYear
        End Get
    End Property

    Public ReadOnly Property Doors As Integer
        Get
            Return Me.carDoors
        End Get
    End Property

    Public ReadOnly Property Cylinders As Integer
        Get
            Return Me.carCylinders
        End Get
    End Property
End Class

Module Example
    Public Sub Main()
        ' Instantiate an Automobile object.
        Dim car1 As New Automobile("Ford", "Model N", 1906, 0, 4)
        Dim car2 As New Automobile("Ford", "Model T", 1909, 2, 4)
        ' Define a resource file named CarResources.resx.
        Using rw As New ResourceWriter(".\CarResources.resources")
            rw.AddResource("Title", "Classic American Cars")
            rw.AddResource("HeaderString1", "Make")
            rw.AddResource("HeaderString2", "Model")
            rw.AddResource("HeaderString3", "Year")
            rw.AddResource("HeaderString4", "Doors")
            rw.AddResource("HeaderString5", "Cylinders")
            rw.AddResource("Information", SystemIcons.Information)
            rw.AddResource("EarlyAuto1", car1)
            rw.AddResource("EarlyAuto2", car2)
        End Using
    End Sub
End Module

Nachdem Sie die RESOURCES-Datei erstellt haben, können Sie die RESOURCES-Datei in eine ausführbare Datei oder Runtimebibliothek einbetten, indem Sie den /resource-Schalter des Sprachcompilers einschließen, oder Sie betten sie mit dem Assembly Linker (Al.exe) in eine Satellitenassembly ein.

Ressourcendateien in Visual Studio

Wenn Sie dem Visual Studio-Projekt eine Ressourcendatei hinzufügen, wird von Visual Studio im Projektverzeichnis eine RESX-Datei erstellt. Visual Studio stellt Ressourcen-Editoren bereit, die es Ihnen ermöglichen, Zeichenfolgen, Bilder und binäre Objekte hinzuzufügen. Da die Editoren nur dazu dienen, statische Daten zu behandeln, können sie nicht zum Speichern programmgesteuerter Objekte verwendet werden. Sie müssen Objektdaten programmgesteuert in eine RESX-Datei oder in eine RESOURCES-Datei schreiben. Weitere Informationen finden Sie in den Abschnitten Programmgesteuertes Arbeiten mit RESX-Dateien und Ressourcen in RESOURCES-Dateien.

Wenn Sie lokalisierte Ressourcen hinzufügen, geben Sie ihnen den gleichen Stammdateinamen wie der Hauptressourcendatei. Sie sollten auch ihre Kultur im Dateinamen festlegen. Wenn Sie z. B. eine Ressourcendatei mit dem Namen Resources.resx hinzufügen, können Sie auch Ressourcendateien mit dem Namen Resources.en-US.resx und Resources.fr-FR.resx erstellen, um lokalisierte Ressourcen für die englische (USA) und französische (Frankreich) Kultur zu halten. Sie sollten auch die Standardkultur der Anwendung festlegen. Die Ressourcen dieser Kultur werden verwendet, wenn keine lokalisierten Ressourcen für eine bestimmte Kultur gefunden werden.

So geben Sie in Visual Studio im Projektmappen-Explorer die Standardkultur an:

  • Öffnen Sie die Projekteigenschaften, klicken Sie mit der rechten Maustaste auf das Projekt, und wählen Sie Eigenschaften aus (oder drücken Sie ALT + EINGABETASTE, wenn das Projekt ausgewählt ist).
  • Wählen Sie die Registerkarte Paket aus.
  • Wählen Sie im Bereich Allgemein im Steuerelement Neutrale Sprache der Assembly die entsprechende Sprache/Kultur aus.
  • Speichern Sie die Änderungen.

Zur Kompilierzeit werden von Visual Studio zuerst die RESX-Dateien in einem Projekt in binäre Ressourcendateien (.resources) konvertiert und im Verzeichnis obj des Projekts in einem Unterverzeichnis gespeichert. Visual Studio bettet alle Ressourcendateien ein, die keine lokalisierten Ressourcen in der vom Projekt generierten Hauptassembly enthalten. Wenn Ressourcendateien lokalisierte Ressourcen enthalten, werden diese von Visual Studio für jede lokalisierte Kultur in separate Satellitenassemblys eingebettet. Anschließend wird jede Satellitenassembly in einem Verzeichnis gespeichert, dessen Name der lokalisierten Kultur entspricht. Lokalisierte englische Ressourcen (USA) werden z. B. in einer Satellitenassembly im Unterverzeichnis "en-US" gespeichert.

Siehe auch