Как я могу извлечь файл из встроенного ресурса и сохранить его на диск?
Я пытаюсь скомпилировать код ниже с помощью 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();
}
}
}
}
Как извлечь DLL файл, который встроен в качестве ресурса, и сохранить его в System32?
Ответы
Ответ 1
Я использую этот (проверенный) метод:
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();
}
}
}
}
Ответ 2
Я бы предложил сделать это проще. Я предполагаю, что ресурс существует, и файл доступен для записи (это может быть проблемой, если мы говорим о системных каталогах).
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);
}
}
}
Ответ 3
Я обнаружил, что самый простой способ сделать это - использовать Properties.Resources
и File
. Вот код, который я использую...
Для двоичных файлов:
File.WriteAllBytes(fileName, Properties.Resources.file);
Для текстовых файлов:
File.WriteAllText(fileName, Properties.Resources.file);
Ответ 4
Это отлично работает!
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
Ответ 5
Попробуйте прочитать целевую сборку в 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()
}
}