119

I am storing a PNG as an embedded resource in an assembly. From within the same assembly I have some code like this:

Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");

The file, named "file.png" is stored in the "Resources" folder (within Visual Studio), and is marked as an embedded resource.

The code fails with an exception saying:

Resource MyNamespace.Resources.file.png cannot be found in class MyNamespace.MyClass

I have identical code (in a different assembly, loading a different resource) which works. So I know the technique is sound. My problem is I end up spending a lot of time trying to figure out what the correct path is. If I could simply query (eg. in the debugger) the assembly to find the correct path, that would save me a load of headaches.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
Rob
  • 4,210
  • 3
  • 30
  • 25

5 Answers5

216

This will get you a string array of all the resources:

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
John
  • 29,788
  • 18
  • 89
  • 130
  • 7
    Hey, How can I get the Resource Folder path to assign it as the root Dir for my embedded http server? – lazzy_ms Aug 02 '18 at 08:44
50

I find myself forgetting how to do this every time as well so I just wrap the two one-liners that I need in a little class:

public class Utility
{
    /// <summary>
    /// Takes the full name of a resource and loads it in to a stream.
    /// </summary>
    /// <param name="resourceName">Assuming an embedded resource is a file
    /// called info.png and is located in a folder called Resources, it
    /// will be compiled in to the assembly with this fully qualified
    /// name: Full.Assembly.Name.Resources.info.png. That is the string
    /// that you should pass to this method.</param>
    /// <returns></returns>
    public static Stream GetEmbeddedResourceStream(string resourceName)
    {
        return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
    }

    /// <summary>
    /// Get the list of all emdedded resources in the assembly.
    /// </summary>
    /// <returns>An array of fully qualified resource names</returns>
    public static string[] GetEmbeddedResourceNames()
    {
        return Assembly.GetExecutingAssembly().GetManifestResourceNames();
    }
}
Dylan
  • 1,658
  • 1
  • 19
  • 25
19

I'm guessing that your class is in a different namespace. The canonical way to solve this would be to use the resources class and a strongly typed resource:

ProjectNamespace.Properties.Resources.file

Use the IDE's resource manager to add resources.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • You are right, my class is in a different namespace. It seems that the Resources folder lives under the namespace specified as the default namespace in the project configuration, which for various reasons isn't the namespace that this class is part of. I suspect you're correct also about using a different approach entirely, but as I need to be consistent with legacy code, that's beyond my control. – Rob Apr 14 '12 at 22:52
  • 10
    This grabs the resource - not it's file path. – Uchiha Itachi Dec 04 '17 at 18:25
  • 3
    @UchihaItachi That's why I offered this answer explicitly as another (and arguably the canonical) way of solving the *underlying problem* rather than answering the question verbatim (which already has an answer at any rate). – Konrad Rudolph Dec 04 '17 at 18:47
  • 1
    @UchihaItachi The question also tells the problem the asking person is facing, what his approach is and how he has tried so far. Although Rudolph does not directly answer the question, he addresses another approach to solve the problem. In most cases, this approach is more convenient, safe, and common. This answer is helpful. I just don't understand why you have to try to shut down people's answers. Vote Up/ Vote Down buttons are there for a reason. – Nin Apr 05 '18 at 06:56
8

I use the following method to grab embedded resources:

protected static Stream GetResourceStream(string resourcePath)
{
    Assembly assembly = Assembly.GetExecutingAssembly();
    List<string> resourceNames = new List<string>(assembly.GetManifestResourceNames());

    resourcePath = resourcePath.Replace(@"/", ".");
    resourcePath = resourceNames.FirstOrDefault(r => r.Contains(resourcePath));

    if (resourcePath == null)
        throw new FileNotFoundException("Resource not found");

    return assembly.GetManifestResourceStream(resourcePath);
}

I then call this with the path in the project:

GetResourceStream(@"DirectoryPathInLibrary/Filename");
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
masterwok
  • 4,868
  • 4
  • 34
  • 41
4

The name of the resource is the name space plus the "pseudo" name space of the path to the file. The "pseudo" name space is made by the sub folder structure using \ (backslashes) instead of . (dots).

public static Stream GetResourceFileStream(String nameSpace, String filePath)
{
    String pseduoName = filePath.Replace('\\', '.');
    Assembly assembly = Assembly.GetExecutingAssembly();
    return assembly.GetManifestResourceStream(nameSpace + "." + pseduoName);
}

The following call:

GetResourceFileStream("my.namespace", "resources\\xml\\my.xml")

will return the stream of my.xml located in the folder-structure resources\xml in the name space: my.namespace.

  • 9
    Also dashes ('-') in the folders are replaced with underscores ('_'). There might be other symbols as well. I'd like to see how the compiler is doing it so we can use the same method. – Boyko Karadzhov Mar 17 '14 at 09:18
  • Boyko is right brackets ( and ) are another that is replaced.. Here is a crude solution... private static List ReplaceWithUnderscore = new List{ "(", ")", "-" }; public static string WrangleToResourceString(string rawString) { var result = rawString; foreach (var replace in ReplaceWithUnderscore) { result = result.Replace(replace, "_"); } return result; } – andrew pate Sep 28 '22 at 17:32