Skip to content

Instantly share code, notes, and snippets.

@RedTeams
Forked from decay88/EmbeddedAssembly.cs
Created August 10, 2022 22:01
Show Gist options
  • Save RedTeams/88267e0c5324ea5e2cb5b38570a0da50 to your computer and use it in GitHub Desktop.
Save RedTeams/88267e0c5324ea5e2cb5b38570a0da50 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
/// <summary>
/// A class for loading an Embedded Assembly
/// </summary>
/// <remarks>
/// Before any coding started, the DLLs have to be added into the project.
/// First, add the DLL as Reference.
/// Then, add the same DLL as file into the project. Right click the project's name > Add > Existing Item...
/// for Referenced DLL, in the properties explorer, change Copy Local = False
/// for Added DLL as File, in the properties explorer, change Build Action = Embedded Resource
/// If you have any other unmanaged / native DLL that is not able to be referenced, then you won't have to reference it, just add the Unmanaged DLL as embedded resource.
/// Obtain EmbeddedAssembly.cs and add it into project.
///
/// Load the DLL from Embedded Resource into Memory. Use EmbeddedAssembly.Load to load it into memory.
/// static class Program
/// {
/// static void Main()
/// {
/// EmbeddedAssembly.Load("MyApp.System.Data.SQLite.dll", "System.Data.SQLite.dll");
/// }
/// }
///
/// Take note about the format of the resource string. Example:
/// MyApp.System.Data.SQLite.dll
/// This string is the Embedded Resource address in the project.
///
/// MyApp is the project name, followed by the DLL filename. If the DLL is added inside a folder, the folder's name must be included in the resource string. Example:
/// MyApp.MyFolder.System.Data.SQLite.dll
///
/// The DLLs are not distributed with the application.
/// When the application fails to locate the DLL, it raises an Event of AppDomain.CurrentDomain.AssemblyResolve.
/// AssemblyResolve request the missing DLL. The Rest is handled by EmbeddedAssembly.cs.
/// </remarks>
namespace GistBook
{
public static class EmbeddedAssembly
{
static Dictionary<string, Assembly> Index = new Dictionary<string, Assembly>();
static EmbeddedAssembly()
{
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
{
if (Index == null || Index.Count == 0) return null;
if (Index.ContainsKey(e.Name)) return Index[e.Name];
return null;
};
}
static void Add(Assembly assembly) { Index.Add(assembly.FullName, assembly); }
/// <summary>
/// Load Assembly, DLL from Embedded Resources into memory.
/// </summary>
/// <param name="EmbeddedResource">Embedded Resource string. Example: WindowsFormsApplication1.SomeTools.dll</param>
/// <param name="FileName">File Name. Example: SomeTools.dll</param>
public static void Load(string EmbeddedResource, string FileName)
{
byte[] ByteArray = null;
using (Stream ResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(EmbeddedResource))
{
// Either the file is not existed or it is not mark as embedded resource
if (ResourceStream == null) throw new Exception(EmbeddedResource + " was not found in Embedded Resources.");
// Get byte[] from the file from embedded resource
ByteArray = new byte[(int)ResourceStream.Length];
ResourceStream.Read(ByteArray, 0, (int)ResourceStream.Length);
try
{
// Add the assembly/dll into dictionary
Add(Assembly.Load(ByteArray));
return;
}
catch
{
bool FileNotWritten = true;
// Define the temporary storage location of the DLL/assembly
string TempFilePath = Path.GetTempPath() + FileName;
using (SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider())
{
// Get the hash value from embedded DLL/assembly
string HashValue = BitConverter.ToString(SHA1.ComputeHash(ByteArray)).Replace("-", string.Empty);
// Determines whether the DLL/assembly is existed or not
if (File.Exists(TempFilePath))
{
// Get the hash value of the existed file
string HashValueOfExistingFile = BitConverter.ToString(
SHA1.ComputeHash(File.ReadAllBytes(TempFilePath))).Replace("-", string.Empty);
// Compare the existed DLL/assembly with the Embedded DLL/assembly
if (HashValue == HashValueOfExistingFile) FileNotWritten = false;
}
}
// Create the file on disk
if (FileNotWritten) File.WriteAllBytes(TempFilePath, ByteArray);
// Add the loaded DLL/assembly into dictionary
Add(Assembly.LoadFrom(TempFilePath));
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment