2012-10-23 30 views
32

Tôi đang cố gắng biên dịch mã dưới đây bằng cách sử dụng CSharpCodeProvider. Tệp được biên dịch thành công, nhưng khi tôi nhấp vào tệp EXE đã tạo, tôi gặp lỗi (Windows đang tìm kiếm giải pháp cho vấn đề này) và không có gì xảy ra.Làm cách nào để trích xuất tệp từ tài nguyên được nhúng và lưu tệp đó vào đĩa?

Khi tôi biên dịch mã dưới đây sử dụng CSharpCodeProvider, tôi đã thêm MySql.Data.dll như một file nguồn nhúng sử dụng dòng mã này:

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

Các tập tin được nhúng thành công (vì tôi nhận thấy kích thước tập tin tăng).

Trong mã bên dưới, tôi cố trích xuất tệp DLL được nhúng và lưu tệp đó vào System32, nhưng mã bên dưới không hoạt động vì một số lý do.

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

Làm cách nào để trích xuất tệp DLL được nhúng dưới dạng tài nguyên và lưu tệp vào System32?

+0

Rafik, bạn nên xem lại câu trả lời của Thomas Sapp dưới đây vì nó hoàn toàn tốt hơn câu trả lời bạn chấp nhận. – motoDrizzt

Trả lời

31

Tôi đã phát hiện ra rằng cách dễ nhất để làm điều này là sử dụng Properties.ResourcesFile. Đây là mã tôi sử dụng ...

Đối với các file nhị phân: File.WriteAllBytes(fileName, Properties.Resources.file);

Đối với các file văn bản: File.WriteAllText(fileName, Properties.Resources.file);

+6

Rất đơn giản. Đây sẽ là câu trả lời được chấp nhận. –

+1

Và điều này hoạt động kể từ Visual Studio 2005/.Net 2.0! Tôi không biết điều gì biện minh cho câu trả lời của năm 2012: P –

+0

Cần bạn tạo tệp tài nguyên trước ... có thể hữu ích khi đi qua việc đưa tệp vào đó, v.v. –

0

Thử đọc lắp ráp mục tiêu của bạn thành một MemoryStream và sau đó lưu vào một FileStream như thế này (xin nhớ rằng mã này không được kiểm tra):

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

Tôi đã sử dụng này (thử nghiệm) phương pháp:

OutputDir: Vị trí nơi bạn muốn sao chép các tài nguyên

ResourceLocation: Namespace (+ dirnames)

Tệp: Danh sách các tệp trong phân bổ lại vị trí, bạn muốn sao chép.

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

Tôi khuyên bạn nên làm điều đó dễ dàng hơn. Tôi cho rằng tài nguyên tồn tại và tệp có thể ghi (đây có thể là vấn đề nếu chúng ta đang nói về các thư mục hệ thống).

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

Đáng nói đến điều này đòi hỏi .NET 4.0 hoặc cao hơn –

1

Điều này hoạt động hoàn hảo!

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

Ví dụ về sử dụng:

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

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

Nếu điều này vẫn không được, thử video này: https://www.youtube.com/watch?v=_61pLVH2qPk

0

Hoặc sử dụng một phương pháp khuyến nông ...

/// <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 ?? [email protected]"{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); 
     } 
    } 
} 
Các vấn đề liên quan