How to Embed Resource Files in .NET Assemblies

his article describes how to use .NET’s ability to embed XML files, icons and other files in an assembly so your code can access them at run-time. Embedding the files helps you avoid problems commonly associated with external files, such as missing files, difficulty locating the files at runtime, and issues with upgrading and versioning.

The ability to embed resources in an application file is not new, but the mechanism for embedding files in .NET is different then for unmanaged code, so don’t expect to be able to work with embedded resources in exactly the same way as you could in unmanaged code.

Microsoft itself frequently embeds resources in application files. For example, if you load an XML file into Internet Explorer (IE), it renders the file in a TreeView-style manner, using different colors for nodes, attributes, and text content. IE accomplishes that by using an embedded resource, an XSLT stylesheet. You can access the stylesheet using the URL res://msxml.dll/DEFAULTSS.XSL (you can type this straight into IE’s address field to see the stylesheet contents).

Author note: You can’t use this technique to access resources embedded within .NET assemblies, because the resource files are not stored in the same way.

Storing Files as Resources in an Assembly
To include a file as a resource inside an assembly, add the file to your project in Visual Studio by dragging it into the Solution Explorer from Windows Explorer, or right-click the project item and select “Add” and then select “Add Existing Item” from the popup menu. After adding the file in your project, select it in the Solution Explorer and then select “Embedded Resource” as the build action in the properties window. (You can also add resources to a managed assembly by using the /resource compiler option if you are compiling your assembly from the command-line).

Select a Build Action
The “Build Action” property tells the compiler what to do with a particular file. Table 1 shows the available options:

Embed Include the file as an embedded resource.
Compile Compile the file.
Content Files designated as content files can be referenced by Visual Studio setup projects.
None Do nothing. Use this action to add documentation or other uncompiled files to your project for reference purposes without embedding them in an assembly.

Accessing Resources at Runtime
To access an embedded resource at runtime, use the GetManifestResourceStream() method of the Assembly class. There are several ways to get an active assembly reference at runtime – some of the common methods are the GetEntryAssembly(), GetExecutingAssembly(), or GetCallingAssembly() methods of the System.Reflection.Assembly class. The following list shows how and when you might want to use each method:

  • GetEntryAssembly: Use this method to reference the executable file that was run to start the current process. The entry assembly is set for Windows forms applications, but for most other applications (for example, web projects), GetEntryAssembly returns ‘nothing’ (or null, in C#).
  • GetExecutingAssembly: Use this method to reference the same assembly that the executing code is in.
  • GetCallingAssembly: Use this method to reference the assembly containing the code that called the current method. This method is useful if you write generic code to read embedded resources that is inside a shared assembly where the embedded resource is in the calling assembly.

The name argument of the GetManifestResourceStream() method identifies your resource, and should match the resource filename. The argument is case-sensitive, regardless of the .NET language you are using.

If you use a default namespace you must prefix the assembly name to the resource name. For example, to access an icon called “icon1.ico” in a project with a default namespace of “myproject”, use the name “myproject.icon1.ico”. In both Visual Basic .NET and C#, new projects have a default namespace?Visual Studio uses the project name by default. You can remove or change the default namespace by right-clicking the project item in the Solution Explorer and selecting Properties from the popup menu. The default namespace appears under the Common Properties, General item (see Figure 1). In VB.NET, it’s the “root namespace”; in C# it’s called the “default namespace”.

Figure 1: Use the Visual Studio Project properties dialog to remove or change the default project namespace.

Although you can use folders (directories) to organize files in your project at design-time, at runtime, all manifest resources are in a “flat” structure (no pathnames, just filenames). If you’re having trouble identifying your resource name, compile your application and use ildasm.exe to view your assembly manifest?the resources are listed in the form “.mresource public [resource name]”.

Build the Sample Application
The sample application for this article consists of a simple Windows Forms application that contains three embedded files: an icon, an XML data file and an XSL style sheet. The following code excerpts demonstrate how to access the embedded resources at runtime.

Examples
Reading an embedded icon

   ' The GetIcon method centralizes the process to   ' retrieve icon resources       ' method to retrieve and assign an icon   Sub ShowIcon      picIcon.Image = GetIcon("Icon1.ico").ToBitmap   End Sub   ' method to retrieve an embedded icon resource   Private Function GetIcon(ByVal strIdentifier As String) As System.Drawing.Icon      ' use the strIdentifier argument to retrieve the       ' appropriate resource from the assembly      With New System.IO.StreamReader( _         [Assembly].GetEntryAssembly. _         GetManifestResourceStream(strIdentifier))         ' read the resource from the returned stream         GetIcon = New System.Drawing.Icon(.BaseStream)         ' close the stream         .Close()      End With   End Function

Reading an embedded XML file

   Sub GetListData      Dim xmlListData As Xml.XmlDocument      Dim xmlItem As Xml.XmlNode         ' The GetXML method centralizes the process to      ' retrieve XML resources      xmlListData = GetXML("listdata.xml")      For Each xmlItem In           xmlListData.DocumentElement.ChildNodes         lstData.Items.Add(xmlItem.InnerText)      Next   End Sub      ' retrieve an embedded XML file    Private Function GetXML(ByVal strIdentifier As String)       As System.Xml.XmlDocument      Dim xmlDoc As New System.Xml.XmlDocument()      ' use the strIdentifier argument to retrieve the       ' appropriate resource from the assembly      With New System.IO.StreamReader( _         [Assembly].GetEntryAssembly. _         GetManifestResourceStream (strIdentifier))         ' load the document from the returned stream             xmlDoc.Load(.BaseStream)         .Close()         ' return the document         GetXML = xmlDoc      End With   End Function

Reading and Parsing an Embedded XSLT Stylesheet

   Sub ParseData     Dim stmOutputStream As New System.IO.MemoryStream()        ' The GetStylesheet method centralizes the process        ' to retrieve XSLT stylesheets, returning them as an      ' instance of the XslTransform class.     GetStylesheet("sample.xslt").Transform( _       GetXML("listdata.xml"), Nothing, stmOutputStream)     txtResults.Text = _       System.Text.Encoding.ASCII.GetString( _       stmOutputStream.ToArray)     stmOutputStream.Close()   End Sub      Private Function GetStylesheet(ByVal strIdentifier As       String) As System.Xml.Xsl.XslTransform      Dim xslSheet As New System.Xml.Xsl.XslTransform()      Dim xslReader = _         New Xml.XmlTextReader( _         Assembly].GetEntryAssembly. _         GetManifestResourceStream(strIdentifier))        xslSheet.Load(xslReader)     xslReader.Close()     GetStylesheet = xslSheet   End Function

Using Visual Studio, embedding files as runtime-accessible resources is easy. Embedding resources within your assembly can help to protect your intellectual property, prevent users from altering application resources and can reduce application deployment difficulties.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts