建立 .NET 應用程式的資源檔

您可以在資源檔中包括資源 (例如字串、影像或物件資料),以讓應用程式輕鬆地使用它們。 .NET Framework 提供五種方式來建立資源檔:

  • 建立包含字串資源的文字檔。 您必須使用資源檔產生器 (resgen.exe) 將文字檔轉換為二進位資源檔 (.resources)。 您接著可以使用語言編譯器將二進位資源檔內嵌在應用程式可執行檔或應用程式程式庫中,或使用組件連結器 (Al.exe) 將它內嵌在附屬組件中。 如需詳細資訊,請參閱文字檔中的資源一節。

  • 建立包含字串、影像或物件資料的 XML 資源 (.resx) 檔案。 您必須使用資源檔產生器 (resgen.exe) 將 .resx 檔案轉換為二進位資源檔 (.resources)。 您接著可以使用語言編譯器將二進位資源檔內嵌在應用程式可執行檔或應用程式程式庫中,或使用組件連結器 (Al.exe) 將它內嵌在附屬組件中。 如需詳細資訊,請參閱 .resx 檔案中的資源一節。

  • 使用 System.Resources 命名空間中的類型,以程式設計方式建立 XML 資源檔 (.resx)。 您可以建立 .resx 檔案、列舉其資源,並依名稱擷取特定資源。 如需詳細資訊,請參閱以程式設計方式使用 .resx 檔案

  • 以程式設計方式建立二進位資源檔 (.resources)。 您接著可以使用語言編譯器將檔案內嵌在應用程式可執行檔或應用程式程式庫中,或使用組件連結器 (Al.exe) 將它內嵌在附屬組件中。 如需詳細資訊,請參閱 .resources 檔案中的資源一節。

  • 使用 Visual Studio 建立資源檔,並將它包含在您的專案中。 Visual Studio 提供可讓您新增、刪除和修改資源的資源編輯器。 在編譯時間,資源檔會自動轉換成二進位 .resources 檔案,並內嵌在應用程式組件或附屬組件中。 如需詳細資訊,請參閱 Visual Studio 中的資源檔一節。

文字檔中的資源

您只能使用文字 (.txt 或 .restext) 檔案來儲存字串資源。 針對非字串資源,請使用 .resx 檔案或以程式設計方式建立它們。 包含字串資源的文字檔的格式如下:

# 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

.txt 和 .restext 檔案的資源檔格式完全相同。 .restext 副檔名只提供可立即將文字檔識別為文字資源檔。

字串資源會以「名稱/值」配對的形式出現,其中「名稱」是識別資源的字串,「值」則是當您將「名稱」傳遞至資源擷取方法 (例如 ResourceManager.GetString) 時所傳回的資源字串。 「名稱」和「值」必須以等號 (=) 分隔。 例如:

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

警告

請勿使用資源檔儲存密碼、安全機密資訊或私用資料。

文字檔中允許空字串 (即其值為 String.Empty 的資源)。 例如:

EmptyString=

從 .NET Framework 4.5 及所有版本的 .NET Core 開始,文字檔案支援使用 #ifdef 符號... #endif#if ! 符號... #endif 建構的條件式編譯。 您接著可搭配使用 /define 參數與資源檔產生器 (resgen.exe) 來定義符號。 每個資源都需要自己的 #ifdefsymbol... #endif#if !symbol... #endif 建構。 如果您使用 #ifdef 陳述式而且已定義 symbol,則 .resources 檔案中會包括相關聯的資源;否則就不會包括該資源。 如果您使用 #if ! 陳述式而且未定義 symbol,則 .resources 檔案中會包括相關聯的資源;否則就不會包括該資源。

註解在文字檔中是選擇性的,並在行首加上分號 (;) 或井字號 (#)。 包含註解的程式行可以放在檔案中的任何地方。 使用資源檔產生器 (resgen.exe) 建立的已編譯 .resources 檔案未包含註解。

文字檔中的任何空白列都會視為空白字元,並且予以忽略。

下列範例定義兩個名為 OKButtonCancelButton 的字串資源。

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

若文字檔包含重複出現的名稱,則資源檔產生器 (resgen.exe) 會顯示警告,並忽略另一個名稱。

「值」不可包含新行字元,但是您可以使用類似 C 語言逸出字元 (例如 \n) 代表新行,以及使用 \t 代表定位點。您也可以包括已逸出的反斜線字元 (例如,「\\」)。 此外,也允許空字串。

依由小到大或由大到小的位元組順序,使用 UTF-8 編碼或 UTF-16 編碼將資源儲存為文字檔格式。 不過,可將 .txt 檔案轉換為 .resources 檔案的資源檔產生器 (resgen.exe),預設會將檔案視為 UTF-8。 如果您想要 Resgen.exe 辨識使用 UTF-16 所編碼的檔案,必須在檔案開頭包括 Unicode 位元組順序標記 (U+FEFF)。

若要將文字格式的資源檔內嵌至 .NET 組件,您必須使用資源檔產生器 (resgen.exe),將檔案轉換成二進位資源 (.resource) 檔。 您接著可以使用語言編譯器將 .resources 檔案內嵌在 .NET 組件中,或使用組件連結器 (Al.exe) 將它內嵌在附屬組件中。

下列範例針對簡單 "Hello World" 主控台應用程式使用名為 GreetingResources.txt 且為文字格式的資源檔。 文字檔會定義 promptgreeting 這兩個字串,提示使用者輸入其名稱並顯示問候語。

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

使用下列命令,以將文字檔轉換成 .resources 檔案:

resgen GreetingResources.txt

下列範例顯示主控台應用程式的原始程式碼,而主控台應用程式使用 .resources 檔案向使用者顯示訊息。

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!

如果您使用 Visual Basic,而且原始程式碼檔案命名為 Greeting.vb,則下列命令會建立包含內嵌 .resources 檔案的可執行檔:

vbc greeting.vb -resource:GreetingResources.resources

如果您使用 C#,而且原始程式碼檔案命名為 Greeting.cs,則下列命令會建立包含內嵌 .resources 檔案的可執行檔:

csc greeting.cs -resource:GreetingResources.resources

.resx 檔案中的資源

與只能儲存字串資源的文字檔不同,XML 資源檔 (.resx) 可以儲存字串;影像、圖示和音訊剪輯這類二進位資料,以及程式化物件。 .resx 檔案包含描述資源項目格式的標準標頭,並指定用來剖析資料之 XML 的版本資訊。 資源檔資料接在 XML 標頭後面。 每個資料項目都會包含 data 標記中所含的名稱/值配對。 其 name 屬性定義資源名稱,而巢狀 value 標記包含資源值。 針對字串資料,value 標記會包含字串。

例如,下列 data 標記會定義名為 prompt 且其值為 "Enter your name:" 的字串資源。

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

警告

請勿使用資源檔儲存密碼、安全機密資訊或私用資料。

針對資源物件,data 標記會包括 type 屬性,以指出資源資料類型。 針對包含二進位資料的物件,data 標記也會包括 mimetype 屬性,以指出二進位資料的 base64 類型。

注意

所有 .resx 檔案都會使用二進位序列化格式子產生和剖析所指定類型的二進位資料。 因此,如果物件的二進位序列化格式以不相容的方式變更,則 .resx 檔案可能會無效。

下列範例顯示 .resx 檔案中包括 Int32 資源和點陣圖影像的一部分。

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

重要

因為 .resx 檔案必須包含具有預先定義格式的格式正確 XML,所以不建議手動使用 .resx 檔案,特別是 .resx 檔案包含字串以外的資源時。 Visual Studio 改為提供一種透明的介面,來建立和操作 .resx 檔案。 如需詳細資訊,請參閱 Visual Studio 中的資源檔一節。 您也可以透過程式設計方式建立和操作 .resx 檔案。 如需詳細資訊,請參閱以程式設計方式使用 .resx 檔案

.resources 檔案中的資源

您可以使用 System.Resources.ResourceWriter 類別,以程式設計方式直接從程式碼建立二進位資源檔 (.resources)。 您也可使用資源檔產生器 (resgen.exe),從文字檔或 .resx 檔案建立 .resources 檔案。 除了字串資料之外,.resources 檔案還可以包含二進位資料 (位元組陣列) 和物件資料。 以程式設計方式建立 .resources 檔案,需要下列步驟:

  1. 建立具有唯一檔案名稱的 ResourceWriter 物件。 做法是將檔案名稱或檔案資料流指定給 ResourceWriter 類別建構函式。

  2. 針對要新增至檔案的每個具名資源,呼叫 ResourceWriter.AddResource 方法的其中一個多載。 資源可以是字串、物件或二進位資料集合 (位元組陣列)。

  3. 呼叫 ResourceWriter.Close 方法,以將資源寫入至檔案,並關閉 ResourceWriter 物件。

注意

請勿使用資源檔儲存密碼、安全機密資訊或私用資料。

下列範例會以程式設計方式建立名為 CarResources.resources 的 .resources 檔案,其中儲存六個字串、一個圖示和兩個應用程式定義的物件 (兩個 Automobile 物件)。 在此範例中,定義和執行個體化的 Automobile 類別會標上 SerializableAttribute 屬性,以便由二進位序列化格式器保存。

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

當您建立 .resources 檔案之後,可以包括語言編譯器的 /resource 切換參數以將它內嵌在執行階段可執行檔或程式庫中,或是使用組件連結器 (Al.exe) 將它內嵌在附屬組件中。

Visual Studio 中的資源檔

當您將資源檔新增至 Visual Studio 專案時,Visual Studio 會在專案目錄中建立 .resx 檔案。 Visual Studio 提供可讓您新增字串、影像和二進位物件的資源編輯器。 因為編輯器設計成只處理靜態資料,所以無法使用它們來儲存程式化物件;您必須以程式設計方式將物件資料寫入 .resx 檔案或 .resources 檔案。 如需詳細資訊,請參閱以程式設計方式使用 .resx 檔案.resources 檔案中的資源章節。

若您要新增當地語系化的資源,請提供它們與主要資源檔相同的根檔案名稱。 您也應在檔案名稱中指定它們的文化特性 (Culture)。 例如,若您新增名稱為 Resources.resx 的資源檔,也可能會建立名稱為 Resources.en-US.resxResources.fr-FR.resx 的資源檔,分別保留英文 (美國) 和法文 (法國) 文化特性的當地語系化資源。 您也應該指定應用程式的預設文化特性。 如果找不到特定文化特性的當地語系化資源,則這是使用其資源的文化特性。

若要指定預設文化特性,請在 Visual Studio 的方案總管中:

  • 開啟專案屬性,以滑鼠右鍵按一下專案,接著選取專案並選取 [屬性 ] (或在已選取專案時按下 Alt + Enter)。
  • 選取 [套件] 索引標籤。
  • 在 [一般] 區域中,從 [組件中性語言] 控制項中選取適當的語言/文化特性。
  • 儲存您的變更。

在編譯時間,Visual Studio 先將專案中的 .resx 檔案轉換成二進位資源檔 (.resources),並將它們儲存在專案 obj 目錄的子目錄中。 Visual Studio 會將未包含當地語系化資源的任何資源檔內嵌在專案所產生的主要組件中。 如果任何資源檔包含當地語系化資源,Visual Studio 會將其內嵌在每個當地語系化文化特性的個別附屬組件中。 它接著會將每個附屬組件儲存在名稱對應至當地語系化文化特性的目錄中。 例如,當地語系化的英文 (美國) 資源會儲存在 en-US 子目錄的附屬組件中。

另請參閱