GPX
GPX

Reputation: 3645

Copying embedded resource as file to disk in C#

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?

Upvotes: 12

Views: 25734

Answers (5)

Gonzo345
Gonzo345

Reputation: 1343

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);
}

Upvotes: 0

Sharif Lotfi
Sharif Lotfi

Reputation: 574

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"

Upvotes: 0

Muhammad Rehan Saeed
Muhammad Rehan Saeed

Reputation: 38537

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;
        }
    }
}

Upvotes: 1

A-Sharabiani
A-Sharabiani

Reputation: 19387

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();

Upvotes: 7

dreadwail
dreadwail

Reputation: 15419

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.

Upvotes: 12

Related Questions