我最终编组代码并像处理 C++ 一样处理它。
关于FindResource() 需要注意的重要一点是,如果您将字符串而不是整数传递给它,它期望lpName 在前面加上#。 MSDN Page
如果字符串的第一个字符是井号 (#),则其余字符表示一个十进制数,用于指定资源名称或类型的整数标识符。例如,字符串“#258”表示整数标识符258。
首先,我将 kernel32.dll 中的所有重要函数编组到一个单独的类中,然后按名称和类型调用资源。 (我从一个博客中获取了大部分此类,但我无法再次找到,如果我再次找到它会链接。)请注意,我已将 FindResource 的参数编组为 strings 而不是整数,因为C# 中的简单性(无需使用MAKEINTRESOURCE 进行黑客攻击)。
ResourceManager.cs
class ResourceManager
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
// public static extern IntPtr FindResource(IntPtr hModule, int lpName, uint lpType);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool EnumResourceNames(IntPtr hModule, string lpType, IntPtr lpEnumFunc, IntPtr lParam);
public static byte[] GetResourceFromExecutable(string lpFileName, string lpName, string lpType)
{
IntPtr hModule = LoadLibrary(lpFileName);
if (hModule != IntPtr.Zero)
{
IntPtr hResource = FindResource(hModule, lpName, lpType);
if (hResource != IntPtr.Zero)
{
uint resSize = SizeofResource(hModule, hResource);
IntPtr resData = LoadResource(hModule, hResource);
if (resData != IntPtr.Zero)
{
byte[] uiBytes = new byte[resSize];
IntPtr ipMemorySource = LockResource(resData);
Marshal.Copy(ipMemorySource, uiBytes, 0, (int)resSize);
return uiBytes;
}
}
}
return null;
}
}
Main.cs
public Main(){
string path = @"C:\sample.exe";
// Get the raw bytes of the resource
byte[] resource = ResourceManager.GetResourceFromExecutable(path, "#106", "KDATA");
}