Skip to content

Instantly share code, notes, and snippets.

@yalayabeeb
Created December 23, 2015 13:09
Show Gist options
  • Save yalayabeeb/e27e2af19474ca748851 to your computer and use it in GitHub Desktop.
Save yalayabeeb/e27e2af19474ca748851 to your computer and use it in GitHub Desktop.
A simple to use class to write data as a resource to a file.
using System;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
public static class Resource
{
#region WinAPI
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
#endregion
#region Native
/// <summary>
/// A fuction to write data as a resource to a file, returning a boolean which tells you whether it was a success or not.
/// </summary>
/// <param name="fileName">The location of the file that you want to write the resource to.</param>
/// <param name="resourceName">The name that you want to give the resource so that it can be read from.</param>
/// <param name="payload">The byte array (the data) that you want to be written to the resource.</param>
/// <returns></returns>
public static bool WriteNative(string fileName, string resourceName, byte[] payload)
{
try
{
IntPtr data = Marshal.AllocHGlobal(payload.Length);
Marshal.Copy(payload, 0, data, payload.Length);
IntPtr handle = BeginUpdateResource(fileName, false);
if (!UpdateResource(handle, "RT_RCDATA", resourceName, 0, data, (uint)payload.Length))
return false;
if (!EndUpdateResource(handle, false))
return false;
Marshal.FreeHGlobal(data);
return true;
}
catch (Exception) { return false; }
}
/// <summary>
/// A function to read a resource from a file specified by the handle of the process, and the name of the resource.
/// </summary>
/// <param name="handle">Use IntPtr.Zero if you want to use the current handle (current application).</param>
/// <param name="resourceName">The name of the resource that was written to.</param>
/// <returns></returns>
public static byte[] ReadNative(IntPtr handle, string resourceName)
{
try
{
IntPtr resHandle = FindResource(handle, resourceName, "RT_RCDATA");
IntPtr loadHandle = LoadResource(handle, resHandle);
uint size = SizeofResource(handle, resHandle);
byte[] data = new byte[size];
Marshal.Copy(loadHandle, data, 0, (int)size);
return data;
}
catch (Exception) { return new byte[0]; }
}
#endregion
#region Managed
/// <summary>
/// A function to write data to a resource file, to have stored in a managed executable.
/// </summary>
/// <param name="resourceFile">The file name where the resource will be written to, typically a ".resource" file.</param>
/// <param name="resourceName">The name that you want to give the resource so that it can be read from.</param>
/// <param name="data">The data that you want to write to the resource.</param>
/// <returns></returns>
public static bool WriteManaged(string resourceFile, string resourceName, object data)
{
try
{
using (var rw = new ResourceWriter(resourceFile))
{
rw.AddResource(resourceName, data);
rw.Close();
}
return true;
}
catch (Exception) { return false; }
}
/// <summary>
/// A function to read a resource file from a managed executable.
/// </summary>
/// <param name="resourceFile">The name of the resource file that is going to be read from.</param>
/// <param name="assembly">The assembly where the resource is stored. Use Assembly.GetExecutingAssembly() for the current, running executable.</param>
/// <param name="resourceName">The name of the resource that was written to.</param>
/// <returns></returns>
public static object ReadManaged(string resourceFile, Assembly assembly, string resourceName)
{
try
{
var rm = new ResourceManager(resourceFile, assembly);
return rm.GetObject(resourceName);
}
catch (Exception) { return null; }
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment