web-dev-qa-db-fra.com

Comment puis-je extraire un fichier d'une ressource intégrée et l'enregistrer sur le disque?

J'essaye de compiler le code ci-dessous en utilisant CSharpCodeProvider. Le fichier est compilé avec succès, mais lorsque je clique sur le fichier EXE généré, j'obtiens une erreur (Windows recherche une solution à ce problème) et rien ne se produit.

Lorsque je compile le code ci-dessous à l'aide de CSharpCodeProvider, j'ai ajouté le MySql.Data.dll en tant que fichier de ressources incorporé utilisant cette ligne de code:

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

Le fichier est correctement intégré (car j'ai remarqué que la taille du fichier a augmenté).

Dans le code ci-dessous, j'essaye d'extraire le fichier DLL DLL intégré et de l'enregistrer dans System32, mais le code ci-dessous ne fonctionne pas pour une raison quelconque.

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

Comment puis-je extraire le fichier DLL incorporé en tant que ressource et l'enregistrer dans System32?

47
Rafik Bari

J'ai trouvé que la façon la plus simple de le faire est d'utiliser Properties.Resources Et File. Voici le code que j'utilise ...

Pour les fichiers binaires: File.WriteAllBytes(fileName, Properties.Resources.file);

Pour les fichiers texte: File.WriteAllText(fileName, Properties.Resources.file);

57
Thomas Sapp

Je suggère de le faire plus facilement. Je suppose que la ressource existe et que le fichier est accessible en écriture (cela pourrait être un problème si nous parlons de répertoires système).

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);
        } 
    }
}
69
Piotr Zierhoffer

J'utilise cette méthode (testée):

OutputDir: emplacement où vous souhaitez copier la ressource

ResourceLocation: namespace (+ dirnames)

Fichiers: liste des fichiers de l'emplacement de ressources que vous souhaitez copier.

    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();
                }
            }
        }
    }
30
M ten Klooster

Ou en utilisant une méthode d'extension ...

 /// <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);
         }
     }
 }
2
BillKrat

Cela fonctionne parfaitement!

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

Exemple d'utilisation:

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

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

Si cela ne vous aide toujours pas, essayez cette vidéo: https://www.youtube.com/watch?v=_61pLVH2qPk

2
Diego Fortes

Essayez de lire votre assemblage cible dans un MemoryStream puis d'enregistrer dans un FileStream comme celui-ci (veuillez garder à l'esprit que ce code n'est pas testé):

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()
    }
}
0
Paul Aldred-Bann