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?
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.
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.
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"?
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With