65

I'm trying to compile the code below using CSharpCodeProvider. The file is successfully compiled, but when I click on the generated EXE file, I get an error (Windows is searching for a solution to this problem) and nothing happens.

When I compile the code below using CSharpCodeProvider, I've added the MySql.Data.dll as an embedded resource file using this line of code:

if (provider.Supports(GeneratorSupport.Resources))
    cp.EmbeddedResources.Add("MySql.Data.dll");

The file is successfully embedded (because I noticed the file size increased).

In the code below, I try to extract the embedded DLL file and save it to System32, but the code below doesn't work for some reason.

namespace ConsoleApplication1
{
    class Program
    {
        public static void ExtractSaveResource(String filename, String location)
        {
            //Assembly assembly = Assembly.GetExecutingAssembly();
            Assembly a = .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();
        }

        static void Main(string[] args)
        {
            try
            {
                string systemDir = Environment.SystemDirectory;
                ExtractSaveResource("MySql.Data.dll", systemDir);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey();
            }
        }
    }
}

How can I extract the DLL file that is embedded as a resource and save it to System32?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rafik Bari
  • 4,867
  • 18
  • 73
  • 123

8 Answers8

91

I'd suggest doing it easier. I assume that the resource exists and the file is writable (this might be an issue if we're speaking about system directories).

public void WriteResourceToFile(string resourceName, string fileName)
{
    using(var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    {
        using(var file = new FileStream(fileName, FileMode.Create, FileAccess.Write))
        {
            resource.CopyTo(file);
        } 
    }
}
Piotr Zierhoffer
  • 5,005
  • 1
  • 38
  • 59
75

I have found that the easiest way to do this is to use Properties.Resources and File. Here is the code I use (requires using System.IO)...

For Binary files: File.WriteAllBytes(fileName, Properties.Resources.file);

For Text files: File.WriteAllText(fileName, Properties.Resources.file);

Thomas Sapp
  • 917
  • 8
  • 10
  • 1
    And this works since Visual Studio 2005 / .Net 2.0 ! I don't know what justifies the answers of 2012 :P – Martin Schneider Jun 17 '16 at 11:42
  • 5
    Needs you to create a resources file first... might be useful to walk through putting files in there, etc. – Craig Brett Feb 20 '17 at 16:06
  • This is absolutely the perfect answer. – motoDrizzt Sep 04 '17 at 12:39
  • Great answer. Just would add you may need to prefix Properties with your ProjectNameSpace like this: ProjectNamespace.Properties.Resources.yourfilename – TinyRacoon Jan 29 '19 at 13:37
  • 9
    It's not the perfect answer because it doesn't explain where project resources come from, for newbies that may be looking at this. See here first >> https://stackoverflow.com/a/90699 THEN use this answer – ataraxia Feb 25 '19 at 12:25
34

I've been using this (tested) method:

OutputDir: Location where you want to copy the resource

ResourceLocation: Namespace (+ dirnames)

Files: List of files within the resourcelocation, you want to copy.

    private static void ExtractEmbeddedResource(string outputDir, string resourceLocation, List<string> files)
    {
        foreach (string file in files)
        {
            using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceLocation + @"." + file))
            {
                using (System.IO.FileStream fileStream = new System.IO.FileStream(System.IO.Path.Combine(outputDir, file), System.IO.FileMode.Create))
                {
                    for (int i = 0; i < stream.Length; i++)
                    {
                        fileStream.WriteByte((byte)stream.ReadByte());
                    }
                    fileStream.Close();
                }
            }
        }
    }
M ten Klooster
  • 351
  • 2
  • 4
4

This works perfectly!

public static void Extract(string nameSpace, string outDirectory, string internalFilePath, string resourceName)
{
    //nameSpace = the namespace of your project, located right above your class' name;
    //outDirectory = where the file will be extracted to;
    //internalFilePath = the name of the folder inside visual studio which the files are in;
    //resourceName = the name of the file;
    Assembly assembly = Assembly.GetCallingAssembly();

    using (Stream s = assembly.GetManifestResourceStream(nameSpace + "." + (internalFilePath == "" ? "" : internalFilePath + ".") + resourceName))
    using (BinaryReader r = new BinaryReader(s))
    using (FileStream fs = new FileStream(outDirectory + "\\" + resourcename, FileMode.OpenOrCreate))
    using (BinaryWriter w = new BinaryWriter(fs))
    {
        w.Write(r.ReadBytes((int)s.Length));
    }
}

Example of usage:

public static void ExtractFile()
{
    String local = Environment.CurrentDirectory; //gets current path to extract the files

    Extract("Geral", local, "Arquivos", "bloquear_vbs.vbs");
}    

If this still doesn't help, try this video out: https://www.youtube.com/watch?v=_61pLVH2qPk

Sebastian
  • 6,293
  • 6
  • 34
  • 47
Diego Fortes
  • 207
  • 2
  • 9
2

Or using an extension method...

 /// <summary>
 /// Retrieves the specified [embedded] resource file and saves it to disk.  
 /// If only filename is provided then the file is saved to the default 
 /// directory, otherwise the full filepath will be used.
 /// <para>
 /// Note: if the embedded resource resides in a different assembly use that
 /// assembly instance with this extension method.
 /// </para>
 /// </summary>
 /// <example>
 /// <code>
 ///       Assembly.GetExecutingAssembly().ExtractResource("Ng-setup.cmd");
 ///       OR
 ///       Assembly.GetExecutingAssembly().ExtractResource("Ng-setup.cmd", "C:\temp\MySetup.cmd");
 /// </code>
 /// </example>
 /// <param name="assembly">The assembly.</param>
 /// <param name="resourceName">Name of the resource.</param>
 /// <param name="fileName">Name of the file.</param>
 public static void ExtractResource(this Assembly assembly, string filename, string path=null)
 {
     //Construct the full path name for the output file
     var outputFile = path ?? $@"{Directory.GetCurrentDirectory()}\{filename}";

     // If the project name contains dashes replace with underscores since 
     // namespaces do not permit dashes (underscores will be default to).
     var resourceName = $"{assembly.GetName().Name.Replace("-","_")}.{filename}";

     // Pull the fully qualified resource name from the provided assembly
     using (var resource = assembly.GetManifestResourceStream(resourceName))
     {
         if (resource == null)
             throw new FileNotFoundException($"Could not find [{resourceName}] in {assembly.FullName}!");

         using (var file = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
         {
             resource.CopyTo(file);
         }
     }
 }
BillKrat
  • 291
  • 2
  • 6
0

Try reading your target assembly into a MemoryStream and then saving to a FileStream like this (please bear in mind that this code isn't tested):

//Imports
using System;
using System.IO;
using System.Reflection;

    Assembly assembly = Assembly.GetExecutingAssembly();
    using (var target = assembly.GetManifestResourceStream("MySql.Data.dll"))
    {
        var size = target.CanSeek ? Convert.ToInt32(target.Length) : 0;

        // read your target assembly into the MemoryStream
        MemoryStream output = null;
        using (output = new MemoryStream(size))
        {
            int len;
            byte[] buffer = new byte[2048];

            do
            {
                len = target.Read(buffer, 0, buffer.Length);
                output.Write(buffer, 0, len);
            } 
            while (len != 0);
        }

        // now save your MemoryStream to a flat file
        using (var fs = File.OpenWrite(@"c:\Windows\System32\MySql.Data.dll"))
        {
            output.WriteTo(fs);
            fs.Flush();
            fs.Close();
        }
    }
Gray Programmerz
  • 479
  • 1
  • 5
  • 22
Paul Aldred-Bann
  • 5,840
  • 4
  • 36
  • 55
0
string roamingfolder = System.IO.Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).FullName
                                                                                                                 + "\\Roaming\\hah";
string roamingfile = System.IO.Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).FullName
                                                                                                                     + "\\Roaming\\hah\\image1.jpg";
Assembly asmbly = Assembly.GetExecutingAssembly();
const string NAME = "image_open2.Resources.Billi1609482658k220y8154.jpg";
if (File.Exists(roamingfile))
    File.Delete(roamingfile);
if (!Directory.Exists(roamingfolder))
    Directory.CreateDirectory(roamingfolder);
using (Stream stream = asmbly.GetManifestResourceStream(NAME))
{
    using (FileStream fileStream = new FileStream(roamingfile, FileMode.Create))
    {
         for (int i = 0; i < stream.Length; i++)
         {
              fileStream.WriteByte((byte)stream.ReadByte());
         }
         fileStream.Close();
    }
 }
  • As it’s currently written, your answer is unclear. Please, add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](https://stackoverflow.com/help/how-to-answer). – Saeid Amini Aug 07 '22 at 12:28
0

No need to complicate. First, add assembly as an embedded resource.

    private void ExtractAssembly(string dll)
    {
         if (!File.Exists(dll))
             File.WriteAllBytes(dll, Resources.MyDLL);
    }

This has perfectly work for me.