SUMMARY
This step-by-step article describes how to use Microsoft Visual Basic
.NET or Microsoft Visual Basic 2005 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:
- 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.
- Right-click your project name, click Add, and then click Add New Item.
- 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.
- 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.
- Right-click either the text file or the bitmap, and then
select Properties.
- 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.
- 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:
Imports System.IO
Imports 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:
Dim _imageStream As Stream
Dim _textStreamReader As StreamReader
Dim _assembly As [Assembly]
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 ex As Exception
MessageBox.Show("Resource wasn't found!", "Error")
End Try
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:
- Add a PictureBox control to the form.
- Add a new Button control to the form, and then change its Text property to Show Image.
- 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 ex As Exception
MessageBox.Show("Image Couldn't be created !")
End Try
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.
- Add a TextBox control to the form.
- Add another Button control to the form, and then change its Text property to Get Text.
- 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 Then
TextBox1.Text = _textStreamReader.ReadLine()
End If
Catch ex As Exception
MessageBox.Show("Error reading stream!")
End Try
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. - Press F5 to run the application.
back to the top
Full code
Imports System.IO
Imports System.Reflection
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call.
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer.
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer.
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button()
Me.PictureBox1 = New System.Windows.Forms.PictureBox()
Me.Button2 = New System.Windows.Forms.Button()
Me.TextBox1 = New System.Windows.Forms.TextBox()
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(16, 196)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Show Image"
'
'PictureBox1
'
Me.PictureBox1.Location = New System.Drawing.Point(8, 8)
Me.PictureBox1.Name = "PictureBox1"
Me.PictureBox1.Size = New System.Drawing.Size(280, 184)
Me.PictureBox1.TabIndex = 1
Me.PictureBox1.TabStop = False
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(16, 232)
Me.Button2.Name = "Button2"
Me.Button2.TabIndex = 2
Me.Button2.Text = "Get Text"
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(100, 232)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(176, 20)
Me.TextBox1.TabIndex = 3
Me.TextBox1.Text = "TextBox1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.TextBox1, Me.Button2, Me.PictureBox1, Me.Button1})
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Dim _imageStream As Stream
Dim _textStreamReader As StreamReader
Dim _assembly As [Assembly]
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
_assembly = [Assembly].GetExecutingAssembly()
_imageStream = _assembly.GetManifestResourceStream("MyNamespace.MyImage.bmp")
_textStreamReader = New StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt"))
Catch ex As Exception
MessageBox.Show("Resource wasn't found!", "Error")
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
PictureBox1.Image = New Bitmap(_imageStream)
Catch ex As Exception
MessageBox.Show("Image Couldn't be created !")
End Try
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Try
If _textStreamReader.Peek() <> -1 Then
TextBox1.Text = _textStreamReader.ReadLine()
End If
Catch ex As Exception
MessageBox.Show("Error reading stream!")
End Try
End Sub
End Class
Note The code should be changed in Visual Basic 2005. If you create a new form that is named
Form1 in
Visual Basic 2005, a Form1.vb file is created for your code and a Form1.Designer.vb file is created that contains the automatically generated part. The Windows Forms
Designer uses the partial keyword to divide the implementation of Form1 into two separate files. This prevents the designer-emitted code
from being interspersed with your code.
For more information about the new Visual Basic 2005 language enhancements, visit the following Microsoft Developer Network (MSDN) Web site:
For more information about partial classes and the Windows Forms Designer, visit the following MSDN 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