using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace DataUtils
{
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class _I_Resources
{
// Flags for LoadLibraryEx
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private const uint LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020;
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr LoadLibraryEx (string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport ("kernel32.dll", SetLastError = true)]
[return: MarshalAs (UnmanagedType.Bool)]
private static extern bool FreeLibrary (IntPtr hModule);
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr GetModuleHandle (string lpModuleName);
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int LoadString (IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);
///
/// Load a string resource from another module (DLL/EXE) identified by file path, or from the current module if filepath is null/empty.
///
/// Path to the module file. If null/empty, use current process module.
/// Resource ID to load.
/// The resource string, or empty string if not found or on error.
public string GetFromOthers (string filepath, uint resid)
{
IntPtr hModule = IntPtr.Zero;
bool needFree = false;
try
{
if (!string.IsNullOrWhiteSpace (filepath))
{
// Load as datafile + image resource so we can access resources without executing DllMain of the module.
hModule = LoadLibraryEx (filepath, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (hModule == IntPtr.Zero)
{
// Failed to load; return empty string
return string.Empty;
}
needFree = true;
}
else
{
// Get handle of current process module (exe)
hModule = GetModuleHandle (null);
if (hModule == IntPtr.Zero)
return string.Empty;
}
// Prepare buffer. Typical string resources are not huge; 4096 should be enough.
const int BUFFER_SIZE = 4096;
StringBuilder sb = new StringBuilder (BUFFER_SIZE);
int copied = LoadString (hModule, resid, sb, sb.Capacity);
if (copied > 0)
{
// LoadString returns number of characters copied (excluding terminating null)
return sb.ToString (0, copied);
}
return string.Empty;
}
finally
{
if (needFree && hModule != IntPtr.Zero)
{
try { FreeLibrary (hModule); }
catch { /* ignore */ }
}
}
}
}
}