Starbeamrainbowlabs

Stardust
Blog

Embedding files in C# binaries

Banner image

You've probably got a whole load of files that your latest program needs to run. You could set them to 'Copy to output directory' and then read them in from there, but this not only causes clutter in your program's output directory, but also potentially exposes files to your users that you don't want them fiddling with or deleting.

The solution: embed them in the program itself! It sounds complex, but it's actually simpler than you'd imagine. In this post I'll show you how to embed files in your solutions and how to interact it them at runtime.

Firstly, you need to set the build action for any files that you'd like to embed to be 'Embedded Resource'. This is slightly different in MonoDevelop and Visual Studio.

In Visual Studio, single click the file in the solution explorer, go to the properties window, find 'Build Action', and select 'Embedded Resource'.

In MonoDevelop, right click the file in the solution explorer, go to the 'Build Action', and then select 'EmbeddedResource'.

Setting the build action in Visual Studio and MonoDevelop.

If you need to edit the .csproj file directly, add the following to the bottom of the <project> tag:

<ItemGroup>
  <EmbeddedResource Include="relative/path/to/filename.ext" />
  <EmbeddedResource Include="relative/path/to/another/filename.ext2" />
</ItemGroup>

It supports wildcards with an asterisk (*) too, if you want to add a whole folder automatically.

Once done, the file will be embedded directly into the parent project's binary when you next hit build. This isn't much use without being able to read it in though - let's do that next.

When files are embedded in C♯ a prefix gets added to them based on the default namespace of the project they are a part of and the folder that they are in. The easiest way to discover what this prefix has been set to is to list all of the files that have been embedded:

string[] resNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
foreach (string resName in resNames)
    Console.WriteLine(resName);

If the above looks a little unfamiliar to you, don't worry. It uses reflection to get a list of files embedded in the currently executing assembly (you'll need to add using System.Reflection; to the top of your file in order to use it too). Reflection is a brilliant tool to obtain all sorts of information about the execution environment you are running in. It's worth a look if you haven't checked it out already.

Adjust the above accordingly if you don't have a console in your project. Now that we've got the name of our embedded file, with some work we can attach a StreamReader to it and read it like any other file:

public static string GetEmbeddedResourceContent(string resourceName)
{
    Assembly asm = Assembly.GetExecutingAssembly();
    Stream stream = asm.GetManifestResourceStream(resourceName);
    StreamReader source = new StreamReader(stream);
    string fileContent = source.ReadToEnd();
    source.Dispose();
    stream.Dispose();
    return fileContent;
}

In a similar fashion to the previous code sample, in the above we get a reference to the currently executing binary, and then we ask it for the Stream that's attached to the embedded file that we want to read. After that, we can attach a StreamReader to it and read the whole thing all at once.

That's all you need to do to embed files into your programs and read them back in again. Sadly you can't write to embedded resources at runtime (they're read only - it would require self-modification), so if you need to change them you could instead unpack them from the binary on load and them modify the unpacked version instead.

If there's anything that you'd like to see me cover, please let me know in the comments below.

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blog bookmarklet booting bug hunting c sharp c++ challenge chrome os code codepen coding conundrums coding conundrums evolved command line compilers compiling compression css dailyprogrammer data analysis debugging demystification distributed computing documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions future game github github gist gitlab graphics hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs learning library linux lora low level lua maintenance manjaro network networking nibriboard node.js operating systems own your code performance photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference releases resource review rust searching secrets security series list server software sorting source code control statistics storage svg talks technical terminal textures thoughts three thing game three.js tool tutorial twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 xmpp xslt

Archive

Art by Mythdael