32

I have an image in a C# WPF app whose build action is set to 'Resource'. It's just a file in the source directory, it hasn't been added to the app's resource collection through the drag/drop properties dialog. I'm trying to write it as a stream, but I can't open it despite trying quite a few variations of dots, slashes, namespaces and seemingly everything else.

I can access it to use elsewhere either in xaml with "pack://application:,,,/Resources/images/flags/tr.png", but I can't get at a stream containing it.

Most places seem to say use

using(BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceBlenderExpress.Resources.images.flags.tr.png"))) {
    using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(imageFile))) {
        while((read = reader.Read(buffer, 0, buffer.Length)) > 0) {
            writer.Write(buffer, 0, read);
        }
        writer.Close();
    }
    reader.Close();
}

Which I haven't had any luck with.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
Echilon
  • 10,064
  • 33
  • 131
  • 217

4 Answers4

36

You're probably looking for Application.GetResourceStream

StreamResourceInfo sri = Application.GetResourceStream(new Uri("Images/foo.png"));
if (sri != null)
{
    using (Stream s = sri.Stream)
    {
        // Do something with the stream...
    }
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
29

GetManifestResourceStream is for traditional .NET resources i.e. those referenced in RESX files. These are not the same as WPF resources i.e. those added with a build action of Resource. To access these you should use Application.GetResourceStream, passing in the appropriate pack: URI. This returns a StreamResourceInfo object, which has a Stream property to access the resource's data.

Phil Devaney
  • 17,607
  • 6
  • 41
  • 33
8

If I get you right, you have a problem to open the resource stream, because you do not know its exact name? If so, you could use

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames()

to get a list of names of all included resources. This way you can find the resource name that was assignd to your image.

Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • 1
    Why not use `GetCallingAssembly` instead of `GetExecutingAssembly`? – Odys Mar 19 '13 at 09:09
  • `Application.ResourceAssembly` is probably the preferred way to get the assembly that contains the resources for your application. Also, this answer is for resx files, NOT WPF Resource Files, which is what this question is about. – Kelly Elton Mar 20 '20 at 04:28
-2

There's no need to call the Close() method, it will be automatically called by Dispose() at the end of the using clause. So your code might look like this:

using(BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceBlenderExpress.Resources.images.flags.tr.png")))
using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(imageFile))) 
{
    while((read = reader.Read(buffer, 0, buffer.Length)) > 0) 
    {
        writer.Write(buffer, 0, read);
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    How does this answer the question? – Frank Bollack Sep 07 '09 at 07:52
  • Really? Useful insight if it's true. I always thought explicitly calling Close was better for streams/files. – Echilon Sep 07 '09 at 12:13
  • The use of the Using statement is explicitly calling the dispose method of the Stream which is implicitly calling the Close method of it. Also the using statement always dispose the "used" object, even if an exception is raised, so the using is an all-inclusive, almost no-fault statement. – BeardinaSuit Aug 12 '10 at 17:36