C# 如何从嵌入式资源中提取文件并将其保存到磁盘?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13031778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I extract a file from an embedded resource and save it to disk?
提问by Rafik Bari
I'm trying to compile the code below using CSharpCodeProvider. The file is successfully compiled, but when I click on the generated EXE file, I get an error (Windows is searching for a solution to this problem) and nothing happens.
我正在尝试使用 CSharpCodeProvider 编译下面的代码。该文件已成功编译,但是当我单击生成的 EXE 文件时,出现错误(Windows 正在寻找此问题的解决方案)并且没有任何反应。
When I compile the code below using CSharpCodeProvider, I've added the MySql.Data.dllas an embedded resource file using this line of code:
当我使用 CSharpCodeProvider 编译下面的代码时,我使用以下代码行将其添加MySql.Data.dll为嵌入式资源文件:
if (provider.Supports(GeneratorSupport.Resources))
cp.EmbeddedResources.Add("MySql.Data.dll");
The file is successfully embedded (because I noticed the file size increased).
文件已成功嵌入(因为我注意到文件大小增加了)。
In the code below, I try to extract the embedded DLL file and save it to System32, but the code below doesn't work for some reason.
在下面的代码中,我尝试提取嵌入的 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();
}
}
}
}
How can I extract the DLL file that is embedded as a resource and save it to System32?
如何提取作为资源嵌入的DLL文件并将其保存到System32?
采纳答案by Thomas Sapp
I have found that the easiest way to do this is to use Properties.Resourcesand File. Here is the code I use (requires using System.IO)...
我发现最简单的方法是使用Properties.Resources和File。这是我使用的代码(需要using System.IO)...
For Binary files:
File.WriteAllBytes(fileName, Properties.Resources.file);
对于二进制文件:
File.WriteAllBytes(fileName, Properties.Resources.file);
For Text files:
File.WriteAllText(fileName, Properties.Resources.file);
对于文本文件:
File.WriteAllText(fileName, Properties.Resources.file);
回答by Paul Aldred-Bann
Try reading your target assembly into a MemoryStreamand then saving to a FileStreamlike this (please bear in mind that this code isn't tested):
尝试将目标程序集读入 aMemoryStream然后FileStream像这样保存到 a (请记住,此代码未经过测试):
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()
}
}
回答by M ten Klooster
I've been using this (tested) method:
我一直在使用这种(经过测试的)方法:
OutputDir: Location where you want to copy the resource
OutputDir:要复制资源的位置
ResourceLocation: Namespace (+ dirnames)
ResourceLocation:命名空间(+ 目录名)
Files: List of files within the resourcelocation, you want to copy.
文件:资源位置中要复制的文件列表。
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();
}
}
}
}
回答by Piotr Zierhoffer
I'd suggest doing it easier. I assume that the resource exists and the file is writable (this might be an issue if we're speaking about system directories).
我建议做得更容易。我假设资源存在并且文件是可写的(如果我们谈论的是系统目录,这可能是一个问题)。
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);
}
}
}
回答by Diego Fortes
This works perfectly!
这工作得很好!
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));
}
}
Example of usage:
用法示例:
public static void ExtractFile()
{
String local = Environment.CurrentDirectory; //gets current path to extract the files
Extract("Geral", local, "Arquivos", "bloquear_vbs.vbs");
}
If this still doesn't help, try this video out: https://www.youtube.com/watch?v=_61pLVH2qPk
如果这仍然没有帮助,试试这个视频:https: //www.youtube.com/watch?v=_61pLVH2qPk
回答by BillKrat
Or using an extension method...
或者使用扩展方法...
/// <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);
}
}
}

