如何使用 Visual C# 內嵌和存取資源

文章翻譯 文章翻譯
文章編號: 319292 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

本文將逐步告訴您,如何使用 Visual C# 將資源內嵌為組件的一部分,然後在執行階段存取資源。

概觀

.NET Framework 可以將檔案封裝為編譯組件的一部分。這些檔案也稱為內嵌資源。這些資源完全不同於與組件關聯的資源和 .resx 檔案。您可以透過 System.Reflection 命名空間的 Assembly 類別,在執行階段存取這些資源。

將資源內嵌至資訊清單的主要優點在於,由於檔案屬於編譯組件的一部分,因此使用者不會無意間刪除或錯置應用程式的關鍵檔案,在某些情況中,這種失誤可能會使程式無法執行。這個方法有個限制,那就是您必須重新編譯程式,才能將對這個檔案所做的任何變更儲存至組件。基於這個原因,請僅將在應用程式存留期不會變更的檔案加入做為內嵌資源。

逐步示範

如果要將內嵌資源加入至您的專案,您必須先加入檔案做為專案的一部分。將檔案加入至專案之後,您就可以透過 System.Reflection 命名空間存取和顯示資源。

加入內嵌資源

如果要將文字檔和影像檔加入至專案,做為內嵌資源,請依照下列步驟執行:
  1. 建立新的 Windows 應用程式專案,做為這次示範之用。這個表單是用來顯示可在執行階段從執行中組件存取的資源。
  2. 用滑鼠右鍵按一下專案名稱,按一下 [加入],然後按一下 [加入新項目]
  3. [新增項目] 對話方塊中,從功能表中選取 [文字檔],然後將檔案命名為 MyTextFile.txt。在整合式開發環境 (IDE) 開啟此檔案時,請加入一些文字,然後關閉檔案。
  4. 重複執行步驟 1 和 2,將點陣圖影像加入至專案,但是對於新增項目類型,不要選取 [文字檔],請選取 [點陣圖檔],然後將檔名變更為 MyImage.bmp。在 IDE 開啟此新影像時,請稍微繪製影像,然後關閉檔案。
  5. 用滑鼠右鍵按一下文字檔或點陣圖,然後選取 [屬性]
  6. [屬性] 對話方塊中,找出 [Build Action] 屬性。根據預設,這個屬性是設定為 [Content]。按一下此屬性,然後將 [Build Action] 屬性變更為 [Embedded Resource]
  7. 針對其他檔案重複執行步驟 4 和 5。
下次建置專案時,編譯器會將這些檔案加入至組件。編譯器會將專案的根命名空間加入至資源名稱 (若隨附於專案的話)。例如,如果專案的根命名空間為 MyNamespace,資源就會命名為 MyNamespace.MyTextFile.txt 和 MyNamespace.MyImage.bmp。

注意:資源檔名稱會區分大小寫。當您存取資源時,必須使用完全相符的檔名拼字和大小寫。如果您未使用完全相符的檔名拼字和大小寫,ManifestResourceStream 的方法呼叫就會傳回 Nothing,而且系統不會引發例外狀況。

注意:如果您要驗證資源名稱,可以使用 Microsoft Intermediate Language 反組譯工具 (ILDASM) 來檢視資訊清單資料,其中列出包含的資源。

存取資源

如果要存取已內嵌在組件資訊清單中的資源,請匯入 System.IOSystem.Reflection 命名空間,如下所示:
   using System.IO;
   using System.Reflection;
				
System.IO 命名空間提供資料流的定義,而 System.Reflection 命名空間會定義 Assembly 類別,此類別會提供方法,以存取內嵌在組件中的資源。

如果您在一般宣告區域宣告下列內容,當載入表單時,程式就會讀取組件中的資源:
   Assembly _assembly;
   Stream _imageStream;
   StreamReader _textStreamReader;
				
注意:如果要在 [程式碼編輯器] 中存取表單的 Load 事件,請按兩下 [設計編輯器] 中的表單。

如果要從正在執行目前程式碼的組件中讀取資源,您必須取得該組件的執行個體。如果要執行這項操作,請使用組件的 GetExecutingAssembly 方法,如下所示:
   _assembly = Assembly.GetExecutingAssembly();
				
讀取資源中的資訊是以 GetManifestResourceStream 的方法呼叫來執行。傳遞至這個方法的參數,即為所要存取之資源的名稱。接著,當執行表單的 Load 事件時,程式會將這兩個資源讀取至其對應的資料流。
   _imageStream = _assembly.GetManifestResourceStream("MyNameSpace.MyImage.bmp");
   _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNameSpace.MyTextFile.txt"));
				
表單的 Load 事件中的程式碼類似下列:
   try
   {
      _assembly = Assembly.GetExecutingAssembly();
      _imageStream = _assembly.GetManifestResourceStream("MyNamespace.MyImage.bmp");
      _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt"));
   }
   catch
   {
      MessageBox.Show("Error accessing resources!");
   }
				
Try-Catch 陳述式 (即為 .NET 中的結構化錯誤處理) 可用來攔截當 Assembly 類別的執行個體存取資源時可能發生的任何錯誤。

顯示資源

這個範例使用兩個按鈕來顯示內嵌資源。當您按一下第一個按鈕時,程式就會建立根據從組件讀取而來的資源為基礎的點陣圖影像,並以表單的 PictureBox 控制項顯示點陣圖影像。第二個按鈕會從文字資源讀取,並將文字顯示在文字方塊中。

如果要顯示內嵌資源,請依照下列步驟執行:
  1. 在表單中加入 [PictureBox] 控制項。
  2. 在表單中加入新的 [Button] 控制項,然後將它的 [Text] 屬性變更為 [Show Image]
  3. 按兩下按鈕,在程式碼檢視器中開啟它的 [Click] 事件,然後將下列程式碼貼入這個事件中:
       try
       {
          pictureBox1.Image = new Bitmap(_imageStream);			       }
       catch 
       {
          MessageBox.Show("Error creating image!");
       }
    					
    這個程式碼會產生新的點陣圖執行個體,此執行個體是以在表單 [Load] 事件中讀取到的資源資料流為基礎。

  4. 在表單中加入 [TextBox] 控制項。
  5. 在表單中加入其他 [Button] 控制項,然後將它的 [Text] 屬性變更為 [Get Text]
  6. 按兩下 [設計編輯器] 中的按鈕,以開啟按鈕的 [Click_Event],然後將下列程式碼貼入此事件中:
       try
       {
          if(_textStreamReader.Peek() != -1)
          {
             textBox1.Text = _textStreamReader.ReadLine();
          }
       }
       catch
       {
          MessageBox.Show("Error writing text!");
       }
    					
    這個程式碼會判斷所要讀取的字元是否仍然存在於資料流中。如果找到字元,文字方塊就會讀入一行。

  7. 按下 F5 以執行此應用程式。

完整程式碼

   using System;
   using System.Drawing;
   using System.Collections;
   using System.ComponentModel;
   using System.Windows.Forms;
   using System.Data;

   using System.IO;
   using System.Reflection;

   namespace MyNamespace
   {
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
         private System.Windows.Forms.PictureBox pictureBox1;
         private System.Windows.Forms.TextBox textBox1;
         private System.Windows.Forms.Button button1;
         private System.Windows.Forms.Button button2;
         /// <summary>
         /// Required designer variable.
         /// </summary>
         private System.ComponentModel.Container components = null;

         public Form1()
         {
            // 
            // Required for Windows Form Designer support.
            // 
            InitializeComponent();

            // 
            // TODO: Add any constructor code after InitializeComponent call.
            // 
         }

         /// <summary>
         /// Clean up any resources being used.
         /// </summary>
         protected override void Dispose( bool disposing )
         {
            if( disposing )
            {
               if (components != null) 
               {
                  components.Dispose();
               }
            }
            base.Dispose( disposing );
         }

      #region Windows Form Designer generated code
         /// <summary>
         /// Required method for Designer support - do not modify
         /// the contents of this method with the code editor.
         /// </summary>
         private void InitializeComponent()
         {
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // pictureBox1
            // 
            this.pictureBox1.Location = new System.Drawing.Point(4, 8);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(284, 192);
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(92, 236);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(192, 20);
            this.textBox1.TabIndex = 1;
            this.textBox1.Text = "textBox1";
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(8, 208);
            this.button1.Name = "button1";
            this.button1.TabIndex = 2;
            this.button1.Text = "Show Image";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(8, 236);
            this.button2.Name = "button2";
            this.button2.TabIndex = 3;
            this.button2.Text = "Get Text";
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.AddRange(new System.Windows.Forms.Control[]{
                                                                     this.button2,
                                                                     this.button1,
                                                                     this.textBox1,
                                                                     this.pictureBox1});

            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
         }
      #endregion

         Assembly _assembly;
         Stream _imageStream;
         StreamReader _textStreamReader;

         /// <summary>
         /// The main entry point for the application.
         /// </summary>
         [STAThread]
         static void Main() 
         {
            Application.Run(new Form1());
         }

         private void Form1_Load(object sender, System.EventArgs e)
         {
            try
            {
               _assembly = Assembly.GetExecutingAssembly();
               _imageStream = _assembly.GetManifestResourceStream("MyNamespace.MyImage.bmp");
              _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt"));
            }
            catch
            {
               MessageBox.Show("Error accessing resources!");
            }		
         }

         private void button1_Click(object sender, System.EventArgs e)
         {
            try
            {
               pictureBox1.Image = new Bitmap(_imageStream);
            }
            catch 
            {
               MessageBox.Show("Error creating image!");
            }
         }

         private void button2_Click(object sender, System.EventArgs e)
         {
            try
            {
               if(_textStreamReader.Peek() != -1)
               {
                  textBox1.Text = _textStreamReader.ReadLine();
               }
            }
            catch
            {
               MessageBox.Show("Error writing text!");
            }		
         }
      }
   }
				
注意 在 Visual Studio 2005 中,程式碼應有所變更。當您建立 Windows Form 專案時,Visual C# 預設會在專案中建立一個表單。這個表單名為 Form1。這兩個表示表單的檔案會命名為 Form1.cs 和 Form1.designer.cs,而您在 Form1.cs 中撰寫程式碼。Designer.cs 檔即為 Windows Form 設計工具寫入程式碼的位置,而所寫入的程式碼會實作您藉由加入控制項來執行的所有動作。 如需有關 Visual C# 2005 中的 Windows Forms 設計工具的詳細資訊,請造訪下列 Microsoft 網站:
http://msdn2.microsoft.com/zh-tw/library/ms173077.aspx

疑難排解

由於資源名稱會區分大小寫,因此,請確認您使用正確的資源名稱拼字和大小寫來存取資源。您可以使用 ILDASM 來讀取資訊清單資料,以確認資源的拼字完全相符。

?考

如需詳細資訊,請參閱下列 Microsoft Developer Network (MSDN) 網站:
System.Reflection 命名空間 (英文)
http://msdn2.microsoft.com/zh-tw/library/system.reflection(en-us,vs.71).aspx

組件類別 (英文)
http://msdn2.microsoft.com/zh-tw/library/system.reflection.assembly(en-us,vs.71).aspx

Assembly.GetManifestResourceStream 方法 (英文)
http://msdn2.microsoft.com/zh-tw/library/system.reflection.assembly.getmanifestresourcestream(en-us,vs.71).aspx

屬性

文章編號: 319292 - 上次校閱: 2008年2月29日 - 版次: 2.10
這篇文章中的資訊適用於:
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual C# 2005 Express Edition
關鍵字:?
kbhowtomaster KB319292
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com