Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where are my resources hidden?

Tags:

.net

resources

I have a program that contains a number of icons in an "Icons" folder (which are included in the project with Build Action=Resource).

In XAML I can access these icons with code such as <Image Source="../Icons/name.png"/> (".." because the XAML is in a different subfolder); however I want to use the same image in some WinForms code in the same project. Unfortunately,

GetType().Assembly.GetManifestResourceStream("Icons/name.png");

returns null and

GetType().Assembly.GetManifestResourceNames()

only lists a bunch of *.resources files (one for each .resx and one called *.g.resources). So how am I supposed to get the image stream?

like image 200
Qwertie Avatar asked Jul 12 '11 21:07

Qwertie


People also ask

What are hidden resources?

These hidden resources, invisible to the human eye, may be subsurface, distant, or not composed of a visible form. Examples of hidden resources include groundwater, minerals, petroleum, porous space, wind, migratory paths, deep oceans, viruses, and planets.

Are resources hidden Catan?

The rules of Settlers of Catan say "each player keeps their resource cards hidden" but in my experience the game is much more fun if resource cards are visible: Much less time spent proposing trades.


2 Answers

I assumed that since I included the images directly in my project that I could directly read them. But thanks to Jack's answer I was able to figure out that they are hidden inside a "resource file" named "ProgramName.g.resources" inside the assembly. To read the image it is necessary to load the resource file first, then search for the image file within the resource file.

ResourceSet.GetObject is case-sensitive, but the image path and filename were converted to lowercase for some reason, so I call ToLowerInvariant on the path name. Here's my solution:

private Stream GetGlobalResourceByPath(Assembly assembly, string path)
{
    string name = assembly.GetManifestResourceNames().Where(n => n.EndsWith(".g.resources")).First();
    Stream outerStream = assembly.GetManifestResourceStream(name);
    ResourceSet resources = new ResourceSet(outerStream);
    return resources.GetObject(path.ToLowerInvariant()) as UnmanagedMemoryStream;
}

I'm not sure how expensive it is to construct a ResourceSet. If it's expensive, and you want to retrieve multiple resources, then you should cache and re-use the ResourceSet object.

Please leave a message if you know why the images end up inside the *.g.resources file. Did Visual Studio choose this name? Is it theoretically possible to put images directly in an assembly, or can assemblies only contain "ResourceSets"?

like image 163
Qwertie Avatar answered Sep 23 '22 07:09

Qwertie


you can find some help from:

http://blog.devarchive.net/2007/12/net-assembly-resource-browser-test.html

http://msdn.microsoft.com/en-us/library/system.io.unmanagedmemorystream.aspx

In the first link, you can find a way to get the resource that is type of UnmanagedMemoryStream, then you should find a way to convert the stream to the type you want.

Hope it helps you!


foreach (var resourceName in ThemeList.Current.GetType().Assembly.GetManifestResourceNames())
{
                var resourceStream = GetType().Assembly.GetManifestResourceStream(resourceName);
                ResourceSet resources = new ResourceSet(resourceStream);
                IDictionaryEnumerator enu = resources.GetEnumerator();
                while (enu.MoveNext())
                {
                    Console.WriteLine(enu.Key); // Key is the resource name and Value is UnmanagedMemoryStream
                }
}
like image 35
Jack Avatar answered Sep 19 '22 07:09

Jack