12

I have an INF file saved as an embedded resource in my C# project. I am trying to save this file to a local location on demand. I am using this method.

public static void SaveResourceToDisk(string ResourceName, string FileToExtractTo)
{
    Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(ResourceName);
    FileStream resourceFile = new FileStream(FileToExtractTo, FileMode.Create);

    byte[] b = new byte[s.Length + 1];
    s.Read(b, 0, Convert.ToInt32(s.Length));
    resourceFile.Write(b, 0, Convert.ToInt32(b.Length - 1));
    resourceFile.Flush();
    resourceFile.Close();

    resourceFile = null;
}

When I try to call this method (passing the resource name along with the namespace name), I get the error:

Object reference not set to an instance of an object

What am I doing wrong here?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
GPX
  • 3,506
  • 10
  • 52
  • 69
  • If you posted the full error (including line number, matched against the line number in your code) it may help in diagnosing the issue. – dreadwail Dec 10 '10 at 05:07
  • 2
    A side tip: Consider using the "using" keyword with your objects to automatically dispose of them. – dreadwail Dec 10 '10 at 05:09
  • 2
    Duplicate of http://stackoverflow.com/questions/864140/write-file-from-assembly-resource-stream-to-disk, which has a more useful code example. – pennyrave Aug 09 '12 at 16:42

5 Answers5

12

You could call

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

And inspect which embedded resources are accessible. Then you can compare that against what you are passing in to see if you are indeed accomplishing what you expected to.

Also, you should consider the using keyword to dispose of your streams:

using(FileStream ResourceFile = new FileStream(FileToExtractTo, FileMode.Create))
{
    //do stuff
}

Good luck.

dreadwail
  • 15,098
  • 21
  • 65
  • 96
  • Okay, got it. I was using `GetManifestResourceStream(namespace.resourcename)` when I should've been usign `GetManifestResourceStream(namespace.Resources.resourcename)`. And thanks for the `using` tip! – GPX Dec 10 '10 at 05:23
6

This is the easiest way to save an embedded resource:

  var stream = assembly.GetManifestResourceStream("name of the manifest resourse");
  var fileStream = File.Create(@"C:\Test.xml");
  stream.Seek(0, SeekOrigin.Begin);
  stream.CopyTo(fileStream);
  fileStream.Close();
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
1

Unpacks all embedded resources within an assembly and saves them alongside the assembly containing this class while maintaining the directory structure. This code does not require you to know anything about the files contained within the assembly and is a more generic solution but it does assume that all files have file extensions.

public class EmbeddedResources
{
    private bool isUnpacked = false;

    public async Task EnsureUnpacked(string saveDirectory)
    {
        if (!this.isUnpacked)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var assemblyDirectory = Path.GetDirectoryName(assembly.Location);
            foreach (var name in assembly.GetManifestResourceNames())
            {
                var stream = assembly.GetManifestResourceStream(name);

                var stringBuilder = new StringBuilder();
                var parts = name
                    .Replace(typeof(EmbeddedResources).Namespace + ".", string.Empty)
                    .Split('.')
                    .ToList();
                for (int i = 0; i < parts.Count; ++i)
                {
                    var part = parts[i];
                    if (string.Equals(part, string.Empty))
                    {
                        stringBuilder.Append(".");      // Append '.' in file name.
                    }
                    else if (i == parts.Count - 2)
                    {
                        stringBuilder.Append(part);     // Append file name and '.'.
                        stringBuilder.Append('.');
                    }
                    else if (i == parts.Count - 1)
                    {
                        stringBuilder.Append(part);     // Append file extension.
                    }
                    else
                    {
                        stringBuilder.Append(part);     // Append file path.
                        stringBuilder.Append('\\');
                    }
                }

                var filePath = Path.Combine(saveDirectory, stringBuilder.ToString());
                using (FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    await stream.CopyToAsync(fileStream);
                }
            }

            this.isUnpacked = true;
        }
    }
}
Muhammad Rehan Saeed
  • 35,627
  • 39
  • 202
  • 311
0

attach your file in your project. click on attached file.go to properties,set set Build Action to Embedded Resource, use file name in code like this: "YourProjectName.YourFileNameIWithExt"

Sharif Lotfi
  • 544
  • 6
  • 13
0

I had an Excel file added into my Resources and had no luck using other's solutions. This was due to the file itself is accessed as a byte[] through the Properties.Resources instead of picking up the string path routing.

So I simply ask the user for a saving path and then I use the System.IO.File.WriteAllBytes method:

using (var save = new SaveFileDialog())
{
    save.Title = "File path for saving the file";
    save.FileName = "Excel file.xlsx";
    save.Filter = "Excel files|*.xlsx;*.xls";
    var dialog = save.ShowDialog();
    if (dialog != DialogResult.OK)
        return;

    System.IO.File.WriteAllBytes(save.FileName, Resources.ExcelFile);
}
Gonzo345
  • 1,133
  • 3
  • 20
  • 42