30

In my application I compile another program from source.cs file using CodeDom.Compiler and I embed some resources ( exe and dll files ) at compile time using :

 // .... rest of code

if (provider.Supports(GeneratorSupport.Resources))
{
    cp.EmbeddedResources.Add("MyFile.exe");
}
if (provider.Supports(GeneratorSupport.Resources))
{
    cp.EmbeddedResources.Add("New.dll");
}
// ....rest of code 

In the compiled file, I need to read the embedded resources as array of bytes. Now I'm doing that by extracting the resources to disk using the function below and the use

File.ReadAllBytes("extractedfile.exe");
File.ReadAllBytes("extracteddll.dll");

I do this after extracting the two files to disk using this function :

public static void ExtractSaveResource(String filename, String location)
{
    //  Assembly assembly = Assembly.GetExecutingAssembly();
    System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
    // Stream stream = assembly.GetManifestResourceStream("Installer.Properties.mydll.dll"); // or whatever 
    // string my_namespace = a.GetName().Name.ToString();
    Stream resFilestream = a.GetManifestResourceStream(filename);
    if (resFilestream != null)
    {
        BinaryReader br = new BinaryReader(resFilestream);
        FileStream fs = new FileStream(location, FileMode.Create); // say 
        BinaryWriter bw = new BinaryWriter(fs);
        byte[] ba = new byte[resFilestream.Length];
        resFilestream.Read(ba, 0, ba.Length);
        bw.Write(ba);
        br.Close();
        bw.Close();
        resFilestream.Close();
    }
    // this.Close(); 
}

How can I do the same thing (Get the embedded resources as array of bytes) but without writing anything to hard disk?

Mo Patel
  • 2,321
  • 4
  • 22
  • 37
Rafik Bari
  • 4,867
  • 18
  • 73
  • 123

5 Answers5

51

You are actually already reading the stream to a byte array, why not just stop there?

public static byte[] ExtractResource(String filename)
{
    System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
    using (Stream resFilestream = a.GetManifestResourceStream(filename))
    {
        if (resFilestream == null) return null;
        byte[] ba = new byte[resFilestream.Length];
        resFilestream.Read(ba, 0, ba.Length);
        return ba;
    }
}

edit: See comments for a preferable reading pattern.

Rotem
  • 21,452
  • 6
  • 62
  • 109
  • 1
    Updated my answer, no need for a memory stream when you're already reading the stream to a byte array. – Rotem May 02 '12 at 11:19
  • 8
    This may not work correctly, because `Stream.Read()` may not return all data in one `Read()`. I'm not sure how does this specific `Stream` behave, but to be on the safe side I would use a `MemoryStream`, `CopyTo()` to that and then use `ToArray()`. – svick May 02 '12 at 12:03
  • @svick : You are right. Alternatively, one may use the reading pattern described in the example on this page: http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx – Rotem May 02 '12 at 12:28
7

Simple alternative using a MemoryStream:

var ms = new MemoryStream();
await resFilestream.CopyToAsync(ms);
var bytes = ms.ToArray();
Saeb Amini
  • 23,054
  • 9
  • 78
  • 76
3

Keep in mind that Embedded resource filename = Assemblyname.fileName

string fileName = "test.pdf";
System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
string fileName = a.GetName().Name + "." + "test.pdf";

using (Stream resFilestream = a.GetManifestResourceStream(fileName))
{
    if (resFilestream == null) return null;
    byte[] ba = new byte[resFilestream.Length];
    resFilestream.Read(ba, 0, ba.Length);
    var byteArray = ba;
}
Peter Hedberg
  • 3,487
  • 2
  • 28
  • 36
Blue Clouds
  • 7,295
  • 4
  • 71
  • 112
  • Can you please fix the formatting to your original intention? – Dejan Sep 03 '19 at 08:44
  • 1
    Worth noting (at least on net5.0) that the resource name is actually prefixed by the assembly root namespace, not the assembly name. So if those are different you've got to be careful with above. – benmccallum Aug 08 '21 at 15:10
  • I agree with @banmccallum that this _is_ worth noting. To get certitude around the names what works for me is to use `var resources = GetType().Assembly.GetManifestResourceNames();` – IVSoftware Nov 17 '21 at 00:20
1

if you are reading an embeded resource here is a simple way to do so.

string resourcePath = "pack://application:,,,/resource/location/S_2/{0}";
        StreamResourceInfo resInfo = Application.GetResourceStream(new Uri(resourcePath));

        if (resInfo == null)
        {
            throw new Exception("Resource not found: " + resourcePath);
        }

        var ms = new System.IO.MemoryStream();
        await resInfo.Stream.CopyToAsync(ms);
        byte[] bytes = ms.ToArray();
jerryurenaa
  • 3,863
  • 1
  • 27
  • 17
-2
File.WriteAllBytes(@"C:\Users\admin\Desktop\MyFile.exe", Resources.BinFile); // binary file
File.WriteAllText(@"C:\Users\admin\Desktop\text.txt", Resources.TextFile); // text file
ZidoX
  • 122
  • 7