Featured Post

Opera 5.0 to ship for Linux

It looks like the Opera browser version 5.0 is going to released for Linux next week. A public beta has been available for sometime but Opera seems to think it is ready for prime time and the $39.00 price tag that goes along with it. If you wish to try on a copy you can grab it here. Anyone out there...

Read More


How To Load an Embedded Resource From A DLL

Posted by Keith Elder | Posted in .Net | Posted on 14-12-2007

When developing class libraries in .Net there are times we utilize XML files to store static information or icons and bitmaps associated with components in our class libraries.  During the build process we have several build actions to choose from that allow us to handle different scenarios.  For icons used in components or static XML files it makes a lot of sense to package those files into the DLL so they can go along for the ride.  We call this an embedded resource. 

For those that are curious the .Net framework has a lot of embedded resources.  For example have you ever wondered where an icon came from after you dragged and dropped a component onto the designer?  Take the BindingNavigator that has icons for next, previous, delete, save, etc.  Those are all embedded within the DLL.  This is great because a developer just adds the one DLL to the project and it works.  No other files need to be added to the solution in order to make the component it work.

If you have a common or standard library that reads a lot of static information from XML files or text files, consider packaging those files as an embedded resource within the DLL.  This way when a user adds your DLL to their project they don’t have to even think about where it is getting its data.  It is already in the DLL.  Let’s look at an example of how this is done.

Embedding Our Data

I created a sample console application and I added an XML file into my solution which holds southern states.  Here is the file:

<?xml version="1.0" encoding="utf-8" ?>
<
SouthernStates>
<
State>
<
Name>Mississippi</Name>
<
Abbreviation>MS</Abbreviation>
</
State>
<
State>
<
Name>Tennesse</Name>
<
Abbreviation>TN</Abbreviation>
</
State>
<
State>
<
Name>Arkansas</Name>
<
Abbreviation>AR</Abbreviation>
</
State>
<
State>
<
Name>Louisiana</Name>
<
Abbreviation>LA</Abbreviation>
</
State>
<
State>
<
Name>Georiga</Name>
<
Abbreviation>GA</Abbreviation>
</
State>
<
State>
<
Name>Florida</Name>
<
Abbreviation>FL</Abbreviation>
</
State>
</
States>

Obviously this information isn’t going to change anytime soon so I can sleep at night knowing this information really doesn’t have to be dynamic and be read from a database.  Here is what my solution in Visual Studio looks like:

image

Right clicking on the SouthernStates.xml file within the project and selecting properties we see the file will be treated as standard content during the build process and will not be copied to the output directory (debug or release). 

image

To make this an Embedded Resource all we have to do is change the “Build Action” to “Embedded Resource”.

image

Now if we do a build on our project and look at the debug folder we only see our host executable along with the EmbeddedResource.Library.dll, and no SouthernStates.xml file.  To check if the XML file is in the DLL open a plain text editor and open the DLL the file was embedded in.  The file embedded should be able to be viewed in plain text with the editor.  Here’s a screen shot using Notepad++.

image

Accessing the Embedded Resource

Embedding the XML into the DLL is the easy part!  The question is how to get this data out so it can be accessed.  It isn’t that hard really.  About two lines of code using Reflection to get the data is all that is needed.   Since this example is using state related information I decided to build this example using a strong typed collection.  In my example I created two classes:  State and StatesCollection.   These classes will provide a strongly typed way of accessing the information in the XML file. 

The State object created has two properties:  Name and Abbreviation.  Basically the properties map to the data in the XML file.   Here is the State class:

    public class State
{
public string Name { get; set; }
public string Abbreviation { get; set; }
}

For the StatesCollection I chose to inherit from a generic list and use a lazy loading property called SouthernStates so the values from the XML file would only get read once.   Taking this approach allows access to all of the features of a generic list (Find(), Sort(), Skip<>, Take<>, etc).  Here is the initial stub of StatesCollection.

public class StatesCollection : System.Collections.Generic.List<State>
{
private StatesCollection()
{

}

private static StatesCollection _southernStates = null;
public static StatesCollection SouthernStates
{
get
{
if (_southernStates == null)
{
}
else
{
return _southernStates;
}
}
}
}

All that is left now is to fill in the code within the getter of our property to load the data from the embedded DLL.  The first thing needed is to get access to the assembly the code is executing within.  The second thing needed is to get the XML document into something we can work with.  Here are the two lines to perform this:

    System.Reflection.Assembly asm = Assembly.GetExecutingAssembly();
System.IO.Stream xmlStream = asm.GetManifestResourceStream("EmbeddedResource.Library.Data.SouthernStates.xml");

The main thing to note is the string passed into GetManifestResourceStream() is the full path including namespace to where the file lives within the project.  Normally if an exception is thrown  when you first try this, this is the cause of the problem.  If the path to the file is not clear then open the DLL with a plain text editor and search for the filename.  Use the path noted in the DLL.  Here’s a screen shot of what this may look like in the DLL:

image

Now that the XML data is in a stream there are several ways to access this data.  In this example I chose to load the stream into an XmlDocument and then process the nodes in the XmlDocument.  The following code fills in the getter property of the SouthernStates property in the StatesCollection class. 

                if (_southernStates == null)
{
StatesCollection states = new StatesCollection();
try
{
System.Reflection.Assembly asm = Assembly.GetExecutingAssembly();
System.IO.Stream xmlStream = asm.GetManifestResourceStream("EmbeddedResource.Library.Data.SouthernStates.xml");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlStream);
XmlNodeList nodes = xmlDoc.SelectNodes("/States/State");
StatesCollection coll = new StatesCollection();
foreach (XmlNode node in nodes)
{
State state = new State();
state.Abbreviation = node["Abbreviation"].InnerText;
state.Name = node["Name"].InnerText;
coll.Add(state);
}
return coll;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
else
{
return _southernStates;
}

Embedded Resource In Action

The hard part is now over.  In the above example notice after GetManifestResourceStream() is called the result is a stream.  Using the stream the XML data can be easily loaded into the XmlDocument using the Load() method.  After the data is loaded into the XmlDocument all that is left is to loop through the XmlDocument and build up a collection of State objects.  To test this example it becomes extremely trivial.  Here is a sample that prints the information in the XML file to the console.

            foreach (State state in StatesCollection.SouthernStates)
{
Console.WriteLine("Name: " + state.Name + " | Abbr: " + state.Abbreviation);
}
Console.ReadLine();

When executed would yield:

image

To take the example a step further LINQ could be used to sort the collection and return values easily.  This is the added benefit of using a strongly typed collection as eluded to earlier.  Here’s a sample using LINQ to sort the abbreviations and return them sorted. 

            var q = from state in StatesCollection.SouthernStates
orderby state.Name ascending
select state.Abbreviation;

List<string> sortedStates = q.ToList<string>();

for (int i = 0; i < sortedStates.Count; i++)
{
Console.WriteLine(sortedStates[i]);
}

When executed would yield:

image

While a little scary at first, embedded resource files aren’t that difficult to deal with and provide a lot of value if used correctly.  Obviously if the data in the XML changes constantly this is going to require a new build of the DLL.  A decision will have to be made on the part of the developer if this is acceptable.  Feel free to download the sample solution below and play around.

Technorati tags: ,
  • Anonymous

    excellent article

  • Anonymous

    This article helped a lot! Many thanks!

  • Anonymous

    This article is toooooooooo good…
    Thanks a lot…

  • Anonymous

    This is great artilce. Everything one may need. Information itself has full support :)

  • Anonymous

    Good article! Thank you.

    May be you can write an article regarding the embedding full DLLs into an EXE?

    I searched over Internet and find molebox, thinstall, but they don’t provide an flexible SDK to manipulate of embedding… Have you tried boxedapp? Looks like what I need…

    Anyway, thank you.

  • Anonymous

    didn’t have to change anything, just misunderstood that. works great thanks

  • http://keithelder.net/blog/ Anonymous

    Did you set the build action to embedded resource?

    Note, you shouldn’t have a dll named embedded resources. The DLL name is setup in your project properties.

  • Anonymous

    Followed your instructions but am not getting the embedded resources dll

  • http://www.sanait.com/ Anonymous

    Great great your r a great Coder.. I love it this article help me to solved my problem to get the resouce file from dlls..

    thank a lot

  • http://keithelder.net/blog/ Anonymous

    I’m not sure what you are asking. Care to repeat?

  • http://www.tommyt.se/ Anonymous

    Do you know if ther is a wasy to embed an aspx page into a dll. For instance to generate an image etc.. ?