C#中如何使用內嵌資源?
本分步指南介紹如何使用 C# 來作為程式集的一部分嵌入資源,然後在運行時訪問資源。
概述
.NET Framework 可以封裝檔案,為已編譯的程式集的一部分。這些檔案稱為內嵌資源。這些資源是完全獨立的程式集相關聯的.resources 和.resx 檔案。您可以在運行時通過的System.Reflection命名空間的程式集類訪問這些資源。
嵌入的清單資源的主要優點是因為這些檔案是已編譯的程式集的一部分,使用者不能意外刪除或誤放到您的應用程式,這在某些情況下可能會阻止程式的執行至關重要的檔案。這種方法的一個限制是您無法儲存任何更改到此檔案的程式集無需重新編譯該程式。正因為如此,只包含作為嵌入資源的應用程式的生存期內將不會更改的檔案。
分步示範
若要將內嵌資源添加到您的項目中,必須首先為您的項目的一部分添加這些檔案。將檔案添加到項目後,您可以訪問和顯示通過System.Reflection命名空間中的資源。
添加內嵌資源
要添加文字檔和影像檔作為資源嵌入到您的項目,請按照下列步驟操作:
為此示範建立一個新的 Windows 應用程式項目。此表單用於顯示從執行的程式集在運行時訪問的資源。
用滑鼠右鍵單擊項目名稱,單擊添加,然後單擊添加新項
在建立項目對話方塊中,從菜單上,選擇文字檔,並命名為 MyTextFile.txt 的檔案。在整合的開發環境 (IDE) 中開啟了該檔案,添加一些文本,,然後關閉該檔案。
重複步驟 1 和 2,將位元影像映像添加到項目中,但而不是作為新的項目類型中選擇文字檔,選擇位元影像檔案,然後將檔案名稱更改為MyImage.bmp。當在 IDE 中開啟新映像時,映像上, 繪製的內容,然後關閉該檔案。
用滑鼠右鍵單擊檔案文本或位元影像,然後選擇屬性
在屬性對話方塊中,找到產生操作屬性。預設情況下,此屬性設定為內容。請單擊該屬性並將產生操作屬性更改為內嵌資源
對另一個檔案重複步驟 4 和 5。
下一次產生項目時,編譯器將這些檔案添加到您的程式集。它包含在項目中時,編譯器會將項目的根命名空間添加到的資源的名稱。例如,如果您的項目的根命名空間是 MyNamespace,資源被命名為 MyNamespace.MyTextFile.txt 和 MyNamespace.MyImage.bmp。
請注意: 資源檔的名稱是區分大小寫。在訪問資源時,您必須使用的確切拼字和大小寫檔案名稱。如果您不使用的確切拼字和大小寫檔案名稱,該方法調用來訪問ManifestResourceStream返回執行任何操作,並且系統不會引發異常。
注意: 如果您想要驗證這些資源名稱,您可以使用 Microsoft 中繼語言拆裝器 (ILDASM) 查看清單資料,其中列出了所包括的資源。
訪問資源
若要訪問已在您的程式集的清單中內嵌資源,導System.IO和System.Reflection命名空間中,按如下所述:
using System.IO; using System.Reflection;
System.IO命名空間提供了流的定義和System.Reflection命名空間中定義的程式集提供的類的方法,以訪問程式集中內嵌資源。
聲明在以下常規聲明地區中的時,在載入表單時讀取從程式集中的資源:
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 中,結構化的錯誤處理用於捕捉的程式集類的執行個體訪問資源時可能發生的任何錯誤。
顯示資源
此樣本使用兩個按鈕以顯示內嵌資源。單擊第一個按鈕時,基於從程式集中讀取資源的位元影像映像建立,並顯示在表單的圖片框控制項中。第二個按鈕的文本資源從讀取,並在文字框中顯示的文本。
若要顯示內嵌資源,請執行以下步驟:
將圖片框控制項添加到表單中。
將一個新的按鈕控制項添加到表單中,然後再將它的Text屬性更改為顯示映像
雙擊該按鈕以開啟其Click事件,在代碼查看器中,然後將下面的代碼粘貼在這種情況:
try { pictureBox1.Image = new Bitmap(_imageStream); } catch { MessageBox.Show("Error creating image!"); }
該代碼產生基於表單的Load事件中讀取資源流的位元影像中的一個新執行個體。
向表單中添加文字框控制項。
將另一個按鈕控制項添加到表單上,然後再將它的Text屬性更改為擷取文本
雙擊設計編輯器中開啟Click_Event的按鈕,該按鈕,然後將下面的代碼粘貼在該事件中:
try { if(_textStreamReader.Peek() != -1) { textBox1.Text = _textStreamReader.ReadLine(); } } catch { MessageBox.Show("Error writing text!"); }
此代碼確定要讀取的字元是否仍然存在在流中。如果找到的字元,文字框中將讀取行。
按 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年中或在 Visual Studio 2008 中,則應更改代碼。建立一個 Windows 表單項目時,Visual C# 一個表單向項目中添加預設情況下。此表單名為 Form1。表示表單的兩個檔案稱為 Form1.cs 和 Form1.designer.cs。Form1.cs 中編寫您的代碼。Designer.cs 檔案是 Windows 表單設計器編寫的代碼實現的所有操作,您通過添加控制項來執行。有關 Windows 表單設計器在 Visual C# 2005年或 Visual Studio 2008 中的詳細資料,請訪問下面的 Microsoft Web 網站:
http://msdn2.microsoft.com/en-us/library/ms173077.aspx
故障排除
由於資源名稱是區分大小寫,請驗證您正在使用相應的拼字和大小寫資源的訪問。您可以使用 ILDASM 讀取清單的資料,來驗證資源的確切拼字。