windowsgm
windowsgm

Reputation: 1616

Embed Text File in Resources

I was trying to embed a Text File into my application in my Resources file. I was following this question post awhile back;

How to embed a text file in a .NET assembly?

I added my Text file into Resources.resx, but can't understand how to call it in code. As you can see the OP had the same problem and managed to get it working using My.Resources.TEXTFILENAME as opposed to the top answers suggestion of Resources.TEXTFILENAME. Unfortunately neither is being recognised in my application and I have tried adding usings but VS isn't suggesting any. Writing Resources by itself, it recognises it as a ResourceDictionary and FrameworkElement.Resources, but no text files... Any ideas?

Upvotes: 6

Views: 18321

Answers (4)

GameAlchemist
GameAlchemist

Reputation: 19294

Add the text file to your project, then define it as content (Build Action=Content) and Copy always to Output.

If you have an installer for your project (standard installer) you can setup the file system so the installer will copy the text file automatically.

to get the folder where the application is running, i use this :

Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly.Location);

If you're using the new installer (ClicOnce) i cannot help you, but i wish you luck :=)

Upvotes: 6

Eric
Eric

Reputation: 3147

If the file is small, the project resource file can be used as described by others, but that way the file can only be retrieved as an Unicode string, potentially/probably twice larger than the original file and loaded into memory at once in its entirety.

The way referred to in the original question is to just put the text file somewhere in your project, select it in Solution Explorer, hit F4 to show Properties, then set Build Action to Embedded resource and leaving Copy to output directory at Do not copy.

This is the same as adding to your .csproj:

<ItemGroup>
    <EmbeddedResource Include="Resources\TextFile.txt"/>
</ItemGroup>

Then you will need either an instance of the correct Assembly, or an IFileProvider to access those resources by name.

Through Assembly:

typeof(Program).Assembly.GetManifestResourceNames()
typeof(Program).Assembly.GetManifestResourceStream(name)
typeof(Program).Assembly.GetManifestResourceInfo(name)

these names are akin class names, dot-separated. If your project is NamespaceName.ProjectName, the resource file is in the Resources subfolder and called TextFile.txt, the resource name is going to be

NamespaceName.ProjectName.Resources.TextFile.txt

There is an overload for GetManifestResourceStream that takes a type so you can do

typeof(Program).Assembly.GetManifestResourceStream(
    typeof(Program),
    "Resources.TextFile.txt")

to never depend on the default namespace or project output file name.

The downside to these is that they don't appear to work from the watches window. You might get an exception

System.ArgumentException "Cannot evaluate a security function."

In that case just write that code some place where you can execute it at will - in a static method for example. So that code runs from your assembly, not the debugger.

And through IFileProvider:

dotnet add package Microsoft.Extensions.FileProviders.Embedded
using Microsoft.Extensions.FileProviders;
var fp = new EmbeddedFileProvider(typeof(Program).Assembly);
// get all resources as an enumerable
foreach (var fileInfo in fp.GetDirectoryContents(""))
    Console.WriteLine($"Name: {fileInfo.Name}, Length: {fileInfo.Length}, ...");
// get a specific one by name
var stream = fp.GetFileInfo("Resources.TextFile.txt").CreateReadStream();

Being an IFileProvider, you could probably try to host .NET Core websites from pure embedded resources.

Upvotes: 3

Joel Peltonen
Joel Peltonen

Reputation: 13402

Embedding textual resources like this seems to work (visual c# express):

  1. Open your project properties
    enter image description here

  2. Browse to resources, click add new and select to create or add existing, whichever is true. enter image description here

  3. A wild resources folder appears enter image description here

  4. Use them like this:

    string foo = global::[ProjectName].Properties.Resources.Muistio;
    string bar = global::[ProjectName].Properties.Resources.asd;
    

The resource Build action is None and Copy to output directory is Do not copy.

It would be great if someone could verify this, it works when the exe is transferred to my server 2k8, but I'd still want independent verification. Especially since ResourceHacker did not see the strings.

Upvotes: 17

McGarnagle
McGarnagle

Reputation: 102723

Using the .ResX resources is slightly different to embedding a text file into your assembly. For the latter, you want to check its properties and make it an EmbeddedResource (ie, there's no need to add anything to a ResX file, just drop the text file into your VS Project). To retrieve it, use this:

Assembly.GetExecutingAssembly().GetManifestResourceStream(name);

To get the correct value for the name parameter, call GetManifestResourceNames() and inspect the results.

Upvotes: 2

Related Questions