Microsoft KB Archive/319292

From BetaArchive Wiki

Article ID: 319292

Article Last Modified on 5/16/2007



APPLIES TO

  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual C# 2005 Express Edition



This article was previously published under Q319292

For a Microsoft Visual Basic .NET version of this article, see 319291.

This article refers to the following Microsoft .NET Framework Class Library namespaces:

  • System.Reflection
  • System.IO

IN THIS TASK

SUMMARY Overview Step-by-Step Demonstration

Full Code Troubleshooting REFERENCES

SUMMARY

This step-by-step article describes how to use Visual C# to embed resources as part of the assembly, and then access the resources at run time.

back to the top

Overview

The .NET Framework can encapsulate files as part of a compiled assembly. These files are known as embedded resources. These resources are completely separate from the .resources and .resx files that are associated with the assembly. You can access these resources at run time through the Assembly class of the System.Reflection namespace.

A major advantage of embedding resources to the Manifest is that because the files are part of your compiled assembly, the user cannot accidentally delete or misplace files that are critical to your application, which in some cases may prevent the execution of your program. One limitation of this approach is that you cannot save any changes to this file to the assembly without recompiling the program. Because of this, only include files that will not change during the lifetime of your application as an embedded resource.

back to the top

Step-by-Step Demonstration

To add embedded resources to your project, you must first add the files as part of your project. After you have added the files to your project, you can access and display the resources through the System.Reflection namespace.

back to the top

Add Embedded Resources

To add a text file and an image file to your project as embedded resources, follow these steps:

  1. Create a new Windows Application project for this demonstration. This form is used to display the resources that are accessed from the executing assembly during run time.
  2. Right-click your project name, click Add, and then click Add New Item.
  3. In the New Item dialog box, select Text File from the menu, and name the file MyTextFile.txt. When the file opens in the integrated development environment (IDE), add some text, and then close the file.
  4. Repeat steps 1 and 2 to add a bitmap image to your project, but instead of selecting Text File as the new item type, select Bitmap File, and then change the file name to MyImage.bmp. When the new image is opened in the IDE, draw something on the image, and then close the file.
  5. Right-click either the text file or the bitmap, and then select Properties.
  6. In the Properties dialog box, locate the Build Action property. By default, this property is set to Content. Click the property and change the Build Action property to Embedded Resource.
  7. Repeat steps 4 and 5 for the other file.

The next time you build the project, the compiler adds these files to your assembly. The compiler adds the root namespace of the project to the name of the resource when it is included in the project. For example, if the root namespace of your project is MyNamespace, the resources are named MyNamespace.MyTextFile.txt and MyNamespace.MyImage.bmp.

NOTE: The resource file names are case-sensitive. When you access the resources, you must use the exact spelling and case of the file name. If you do not use the exact spelling and case of the file name, the method call to access the ManifestResourceStream returns Nothing, and the system does not raise an exception.

NOTE: If you want to verify the resource names, you can use the Microsoft Intermediate Language Disassembler (ILDASM) to view the Manifest data, which lists the included resources.

back to the top

Access Resources

To access the resources that you have embedded in the Manifest of your assembly, import the System.IO and the System.Reflection namespaces, as follows:

   using System.IO;
   using System.Reflection;
                

The System.IO namespace provides the definition of a stream and the System.Reflection namespace defines the Assembly class that provides methods to access the resources that are embedded in your assembly.

When you declare the following in the general declaration area, the resources from the assembly are read when the form is loaded:

   Assembly _assembly;
   Stream _imageStream;
   StreamReader _textStreamReader;
                

NOTE: To access the Load event for the form in the Code Editor, double-click the form in the Design Editor.

To read the resource from the assembly that is executing the current code, you must obtain an instance of that assembly. To do this, use the GetExecutingAssembly method of the assembly, as follows:

   _assembly = Assembly.GetExecutingAssembly();
                

Reading the information from the resource to a stream is performed with a method call to GetManifestResourceStream. The parameter that is passed to this method is the name of the resource that is to be accessed. The two resources are then read to their corresponding streams as the Load event of the form is executed.

   _imageStream = _assembly.GetManifestResourceStream("MyNameSpace.MyImage.bmp");
   _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNameSpace.MyTextFile.txt"));
                

The code in the Load event for the form resembles the following:

   try
   {
      _assembly = Assembly.GetExecutingAssembly();
      _imageStream = _assembly.GetManifestResourceStream("MyNamespace.MyImage.bmp");
      _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt"));
   }
   catch
   {
      MessageBox.Show("Error accessing resources!");
   }
                

The Try-Catch statement, known as structured error handling in .NET, is used to catch any errors that may have occurred while the instance of the Assembly class accesses the resources.

back to the top

Display Resources

This example uses two buttons to display the embedded resources. When you click the first button, a bitmap image that is based on the resource that is read from the assembly is created and displayed in the PictureBox control of the form. The second button reads from a text resource and displays the text in a text box.

To display the embedded resources, follow these steps:

  1. Add a PictureBox control to the form.
  2. Add a new Button control to the form, and then change its Text property to Show Image.
  3. Double-click the button to open its Click event in the code viewer, and then paste the following code in this event:

       try
       {
          pictureBox1.Image = new Bitmap(_imageStream);                }
       catch 
       {
          MessageBox.Show("Error creating image!");
       }
                        

    This code generates a new instance of a bitmap that is based on the resource stream that was read in the Load event of the form.

  4. Add a TextBox control to the form.
  5. Add another Button control to the form, and then change its Text property to Get Text.
  6. Double-click the button in the Design Editor to open the Click_Event for the button, and then paste the following code in the event:

       try
       {
          if(_textStreamReader.Peek() != -1)
          {
             textBox1.Text = _textStreamReader.ReadLine();
          }
       }
       catch
       {
          MessageBox.Show("Error writing text!");
       }
                        

    This code determines whether characters to be read still exist in the stream. If characters are found, a line is read to the text box.

  7. Press F5 to run the application.

back to the top

Full Code

   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!");
            }       
         }
      }
   }
                

Note The code should be changed in Visual Studio 2005. When you create a Windows Forms project, Visual C# adds one form to the project by default. This form is named Form1. The two files that represent the form are named Form1.cs and Form1.designer.cs. You write your code in Form1.cs. The Designer.cs file is where the Windows Forms Designer writes the code that implements all the actions that you performed by adding controls. For more information about the Windows Forms Designer in Visual C# 2005, visit the following Microsoft Web site:

back to the top

Troubleshooting

Because resource names are case-sensitive, verify that you are using the correct spelling and case of the resources that are accessed. You can use ILDASM to read the Manifest data to verify the exact spelling of the resources.

back to the top

REFERENCES

For more information, see the following Microsoft Developer Network (MSDN) Web sites:

back to the top

Keywords: kbhowtomaster KB319292