3

I have a file I need to access at runtime, I've included it in my project and set it up as embedded resource (it's actually a source file, I changed the extension to .cs.txt to get around VS trying to compile it. That shouldn't matter, but I'm mentioning it anyway just in case). When I try getting the file

var assembly = Assembly.GetExecutingAssembly();
Stream stream = assembly.GetManifestResourceStream(resourceName);

I get a null. I've made sure I'm using the Namespace.Folder.Filename notation, but that didn't help. It appears the file is actually not there, because when I call

assembly.GetManifestResourceNames();

I get an empty string array. Any idea what could be the case?

Jester
  • 56,577
  • 4
  • 81
  • 125
Shaggydog
  • 3,456
  • 7
  • 33
  • 50
  • Is the file marked as Embedded Resource in your project file ? – Ondrej Svejdar Sep 10 '14 at 19:32
  • Yes it is. I've also made sure that the assembly was rebuilt after I added it. – Shaggydog Sep 10 '14 at 19:42
  • The resource file must be in a project folder named "Resources", and must be marked as an embedded resource in the properties window. Be careful if Visual Studio has maybe copied it from Resources to the main folder and that is the copy that is included in the project. And the assembly that is used in the GetManifestResourceNames() or GetManifestResourceStream() call must be the assembly that the resource was embedded in, which may not necessarily be the assembly returned by Assembly.GetExecutingAssembly(). – RenniePet Sep 10 '14 at 19:55
  • "must be marked as an embedded resource in the properties window. " - this is the case, I've already said that. "the assembly that is used in the GetManifestResourceNames() or GetManifestResourceStream() call must be the assembly that the resource was embedded in" - I've made sure I'm loading the right assembly. "The resource file must be in a project folder named "Resources"" - this is news to me, none of the materials mentioned it. However, I tried to rename the folder in question to "Resources". It didn't help. – Shaggydog Sep 10 '14 at 20:33
  • 1
    Sorry, you're right, the resource files do not necessarily have to be in a folder named "Resources". Could you put a breakpoint on the "var assembly = Assembly.GetExecutingAssembly();" and check that the assembly returned is the same assembly that the resource files are embedded in? – RenniePet Sep 10 '14 at 20:49
  • Once again, I have made sure that I'm loading the correct assembly. – Shaggydog Sep 10 '14 at 20:54
  • If you'd be right then you wouldn't be here. GetManifestResourceNames() tells you that your assumptions are wrong. Plenty of reasons for this, GetExecutingAssembly() is a pretty brittle way to guess at the assembly when the jitter optimizer can inline methods for example. This is the core reason that Microsoft decided to add the resource designer to VS. You found a good reason to use it. – Hans Passant Sep 10 '14 at 22:52
  • 3
    If it were as trivial as RenniePet is suggesting, I wouldn't be here. I understand that he was trying to help, but when I have to reiterate "yes I've done that" more than twice, I get a bit exasperated. I still think I kept my tone civil with him. Maybe that's something you could work on as well. – Shaggydog Sep 11 '14 at 07:13

3 Answers3

7

I appreciate this is an old thread but what I found this morning might be useful to others.

I had a resource where the filename had multiple dots in it...

example filename: data.txt.dat

var resources = asm.GetManifestResourceNames(); // None found (empty array)

renamed to data.txt (still just an embedded resource in the project configuration

var resources = asm.GetManifestResourceNames(); // Entry found ("Assembly.Namespace.data.txt")

So maybe there is some limitation around multiple . characters in the name

Sam Lad
  • 267
  • 5
  • 14
  • I can confirm your observation. I don't why, but a resource `resource.deDE.js` shows up, while `resource.de.js` doesn't. – Lukas-T Sep 09 '21 at 10:33
  • seems to be a known issue of dotnet : https://github.com/dotnet/sdk/issues/13395 still open – Drakkin Nov 29 '22 at 13:00
1

So I got around this by using the VS resource manager. Now I can access the file directly like this:

MyNamespace.Properties.Resources.MyFile

I'd recommend this approach to anyone, as it seems not only much cleaner, but safer as well. Thanks Hans Passant for the advice.

Shaggydog
  • 3,456
  • 7
  • 33
  • 50
  • I was googling how to embed a DLL within an EXE and then extract it and copy it out to disk (in this case I did not need to add it dynamically as a reference). Your approach is way more straight forward than the approaches listed here - https://stackoverflow.com/q/189549 – Chris Smith Jun 23 '18 at 00:22
0

Based on this pull request (https://github.com/dotnet/msbuild/pull/5824) you can add WithCulture="false" in your csproj on your EmbeddedResource tag :

<EmbeddedResource Include="a.cs.b" WithCulture="false"/>

It is working for me

Drakkin
  • 878
  • 12
  • 27