Ich versuche, den folgenden Code mit CSharpCodeProvider zu kompilieren. Die Datei wurde erfolgreich kompiliert, aber wenn ich auf die generierte EXE-Datei klicke, erhalte ich eine Fehlermeldung (Windows sucht nach einer Lösung für dieses Problem) und es passiert nichts.
Wenn ich den folgenden Code mit CSharpCodeProvider kompiliere, habe ich das MySql.Data.dll
als eingebettete Ressourcendatei mit folgender Codezeile:
if (provider.Supports(GeneratorSupport.Resources))
cp.EmbeddedResources.Add("MySql.Data.dll");
Die Datei wurde erfolgreich eingebettet (da die Dateigröße zugenommen hat).
Im folgenden Code versuche ich, die eingebettete DLL) - Datei zu extrahieren und auf System32 zu speichern, aber der folgende Code funktioniert aus irgendeinem Grund nicht.
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();
}
}
}
}
Wie kann ich die als Ressource eingebettete DLL Datei extrahieren und auf System32 speichern?
Ich habe festgestellt, dass der einfachste Weg dies zu tun ist, Properties.Resources
Und File
zu verwenden. Hier ist der Code, den ich benutze ...
Für Binärdateien: File.WriteAllBytes(fileName, Properties.Resources.file);
Für Textdateien: File.WriteAllText(fileName, Properties.Resources.file);
Ich würde vorschlagen, es einfacher zu machen. Ich gehe davon aus, dass die Ressource vorhanden und die Datei beschreibbar ist (dies kann ein Problem sein, wenn es sich um Systemverzeichnisse handelt).
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);
}
}
}
Ich habe diese (getestete) Methode verwendet:
OutputDir: Speicherort, an den Sie die Ressource kopieren möchten
ResourceLocation: Namespace (+ dirnames)
Dateien: Liste der Dateien im Ressourcenverzeichnis, die Sie kopieren möchten.
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();
}
}
}
}
Oder mit einer Erweiterungsmethode ...
/// <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);
}
}
}
Das funktioniert einwandfrei!
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));
}
}
Anwendungsbeispiel:
public static void ExtractFile()
{
String local = Environment.CurrentDirectory; //gets current path to extract the files
Extract("Geral", local, "Arquivos", "bloquear_vbs.vbs");
}
Wenn dies immer noch nicht hilft, probieren Sie dieses Video aus: https://www.youtube.com/watch?v=_61pLVH2qPk
Versuchen Sie, Ihre Ziel-Assembly in ein MemoryStream
einzulesen und dann in ein FileStream
zu speichern (denken Sie daran, dass dieser Code nicht getestet wurde):
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()
}
}