Have you ever found that sleek application you wrote slowly becoming scattered over time with the use of external files? Say you want to create a simple GUI application that can be distributed as just an executable file. What if you want to use a *.chm help file? This article will show how to embed that file in your executable via the .NET concept of Resources. Note: To view full-sized images in this post, click on the thumbnails.
First, we start by opening the Project configuration by right-clicking the "My Project" object in the Solution Explorer and selecting "Open."
Next, make sure you have selected the "Resources" tab in the configuration list.
Here's where your options may differ. If you want to track the file you're including as a Resource by associating it with your project, you can drag that file from an Explorer window into your project.
The file is now a part of your project, and as such, will show up in the Solution Explorer.
Now, drag the file from Solution Explorer into the Resources panel to include it as a resource in your compiled solution.
If you don't want to track the file by associating it with your project, you can just as easily drag the file directly into the Resources panel. Keep in mind, though, that every time you compile your project, the Resources will have to call on their physical counterparts. If the file is missing, that Resource will fail to be added to the compiled project.
Be sure to save your Project configuration after adding the resource.
At this point, you have the Resource available to your .NET project through an object called the ResourceManager. The easiest way to access this object is by calling My.Resources.NameOfTheResource. The NameOfTheResource will be whatever name Visual Studio assigned to your Resource when you added it (or the name you configured for yourself after dragging it in). The file "rexCrawler.chm" was given the Resource name "rexCrawler".
This code will check if the file to be generated from the resource hasn't already been generated by using a Static variable (that will be set in code further below) called helpFile, which stores the path for the physical resource after it has been written. Its default value is Nothing.
1 2 3 4 5 6 7 8
If helpFile = Nothing _ Or Not My.Computer.FileSystem.FileExists(helpFile) _ Then helpFile = IO.Path.GetTempPath & "rexCrawler.chm" ExtractHelpToFile() End If Help.ShowHelp(Me, helpFile)
The following code represents the contents of the ExtractHelpToFile() Sub. It uses IO.Path.GetTempPath to find a suitable location to write the Resource file to, and then employs a MemoryStream to read from the ResourceManager and a FileStream to write to the physical location.
1 2 3 4 5 6 7 8 9 10 11 12
Dim resource As IO.Stream = New IO.MemoryStream(My.Resources.rexCrawler) Dim output As IO.Stream = _ New IO.FileStream(helpFile, IO.FileMode.Create, IO.FileAccess.Write) Dim bytes(4096) As Byte Dim bytesread As Integer = 0 While resource.Position < resource.Length - 1 bytesread = resource.Read(bytes, 0, bytes.Length) output.Write(bytes, 0, bytesread) End While output.Close()]
This method can be adapted to any type of binary file you wish to write to a temporary location. I would also recommend using a version number or build number in your resource's temporary file name, so that new versions can't possibly get stuck using an outdated file.
There are methods available to you for more common file types (such as images). Just keep in mind--the ResourceManager will give you the data as a Byte array. If you can find constructors that will allow a Byte array as their input source, you're in business.
The preceding code has been taken directly from rexCrawler v126.96.36.199 source. I, Todd Boyd, the author of this blog and of the rexCrawler software, allow the use of the source code posted here for non-profit and personal use.