c# .net embedded-resource csharpcodeprovider

c# - ¿Cómo puedo extraer un archivo de un recurso incrustado y guardarlo en el disco?



.net embedded-resource (6)

Descubrí que la forma más fácil de hacerlo es usar Properties.Resources . Properties.Resources y File . Aquí está el código que uso ...

Para archivos binarios: File.WriteAllBytes(fileName, Properties.Resources.file);

Para archivos de texto: File.WriteAllText(fileName, Properties.Resources.file);

Estoy intentando compilar el siguiente código usando CSharpCodeProvider. El archivo se compiló con éxito, pero cuando hago clic en el archivo EXE generado, aparece un error (Windows está buscando una solución a este problema) y no ocurre nada.

Cuando compilo el código a continuación usando CSharpCodeProvider, he agregado MySql.Data.dll como un archivo de recursos incrustado usando esta línea de código:

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

El archivo está incrustado correctamente (porque noté que el tamaño del archivo aumentó).

En el siguiente código, intento extraer el archivo DLL incrustado y guardarlo en System32, pero el código siguiente no funciona por algún motivo.

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

¿Cómo puedo extraer el archivo DLL que está incrustado como un recurso y guardarlo en System32?


Esto funciona perfectamente!

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

Ejemplo de uso:

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

Si esto aún no funciona, prueba este video: https://www.youtube.com/watch?v=_61pLVH2qPk


He estado usando este método (probado):

OutputDir: ubicación donde desea copiar el recurso

ResourceLocation: Namespace (+ dirnames)

Archivos: lista de archivos dentro de la ubicación de recursos, que desea copiar.

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


Intente leer su ensamblaje de destino en un MemoryStream y luego guarde en un FileStream esta manera (tenga en cuenta que este código no está probado):

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


O usando un método de extensión ...

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


Sugeriría hacerlo más fácil. Supongo que el recurso existe y el archivo es de escritura (esto podría ser un problema si hablamos de directorios del sistema).

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