2012-10-23 109 views
32

我想使用CSharpCodeProvider编译下面的代码。该文件已成功编译,但是当我单击生成的EXE文件时,出现错误(Windows正在寻找解决此问题的解决方案),但没有任何反应。如何从嵌入式资源提取文件并将其保存到磁盘?

当我编译下面使用CSharpCodeProvider的代码,我已经添加了MySql.Data.dll为使用该行代码嵌入的资源文件:

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

该文件被成功嵌入(因为我注意到,文件大小增加)。

在下面的代码中,我尝试提取嵌入的DLL文件并将其保存到System32,但下面的代码由于某种原因不起作用。

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

如何提取嵌入为资源并将其保存到System32的DLL文件?

+0

哈里,你应该在下面回顾Thomas Sapp的答案,因为它比你接受的答案要好得多。 – motoDrizzt

回答

31

我发现,要做到这一点最简单的方法是使用Properties.ResourcesFile。下面是我使用的代码...

对于二进制文件: File.WriteAllBytes(fileName, Properties.Resources.file);

的文本文件: File.WriteAllText(fileName, Properties.Resources.file);

+6

如此简单。这应该是被接受的答案。 –

+1

从Visual Studio 2005/.Net 2.0开始,它就可以工作!我不知道2012年答案的理由是什么:P –

+0

需要您先创建一个资源文件...可能对将文件放在那里等有帮助 –

0

尝试阅读你的目标组装成一个MemoryStream,然后保存为FileStream这样的(请记住,此代码未测试):

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
我一直在使用这种

(测试)方法:

OutputDir:要复制的资源

ResourceLocation地点:命名空间(+ dirnames中)

文件:要复制的资源位置内的文件列表。

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

我建议这样做更容易。我假定资源存在,文件是可写的(如果我们正在谈论系统目录,这可能是一个问题)。

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

值得一提的是.NET 4.0或以上版本 –

1

这很完美!用法

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

例子:

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

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

如果仍然没有帮助,试试这个视频输出:https://www.youtube.com/watch?v=_61pLVH2qPk

0

或使用扩展方法...

/// <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); 
     } 
    } 
} 
相关问题