Hoe kan ik een bestand uit een ingesloten bron extraheren en op schijf opslaan?

Ik probeer de onderstaande code te compileren met CSharpCodeProvider. Het bestand is succesvol gecompileerd, maar wanneer ik op het gegenereerde EXE-bestand klik, krijg ik een foutmelding (Windows zoekt naar een oplossing voor dit probleem) en gebeurt er niets.

Als ik de onderstaande code compileer met CSharpCodeProvider, heb ik de MySql.Data.dlltoegevoegd als een ingesloten bronbestand met deze regel code:

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

Het bestand is succesvol ingesloten (omdat ik merkte dat de bestandsgrootte toenam).

In de onderstaande code probeer ik het ingesloten DLL-bestand uit te pakken en op te slaan in System32, maar de onderstaande code werkt om de een of andere reden niet.

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

Hoe kan ik het DLL-bestand dat als bron is ingesloten uitpakken en opslaan in System32?


Antwoord 1, autoriteit 100%

Ik stel voor om het gemakkelijker te doen. Ik neem aan dat de bron bestaat en dat het bestand beschrijfbaar is (dit kan een probleem zijn als we het hebben over systeemmappen).

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

Antwoord 2, autoriteit 89%

Ik heb ontdekt dat de gemakkelijkste manier om dit te doen is om Properties.Resourcesen Filete gebruiken. Hier is de code die ik gebruik (vereist using System.IO)…

Voor binaire bestanden:
File.WriteAllBytes(fileName, Properties.Resources.file);

Voor tekstbestanden:
File.WriteAllText(fileName, Properties.Resources.file);


Antwoord 3, autoriteit 38%

Ik heb deze (geteste) methode gebruikt:

OutputDir: locatie waar u de bron wilt kopiëren

ResourceLocation: naamruimte (+ dirnamen)

Bestanden: lijst met bestanden binnen de bronlocatie die u wilt kopiëren.

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

Antwoord 4, autoriteit 5%

Dit werkt perfect!

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

Voorbeeld van gebruik:

public static void ExtractFile()
{
    String local = Environment.CurrentDirectory; //gets current path to extract the files
    Extract("Geral", local, "Arquivos", "bloquear_vbs.vbs");
}    

Als dit nog steeds niet helpt, probeer dan deze video: https://www.youtube .com/watch?v=_61pLVH2qPk


Antwoord 5, autoriteit 2%

Of een extensiemethode gebruiken…

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

Antwoord 6

Probeer uw doelassemblage in een MemoryStreamte lezen en vervolgens op te slaan in een FileStreamzoals deze (houd er rekening mee dat deze code niet is getest):

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

Other episodes