FindResource不;尽管资源确实存在,但找不到资源
本文关键字:资源 存在 找不到 FindResource | 更新日期: 2023-09-27 18:00:22
我的手指受伤了。我正在尝试使用WinApi(FindResource)从我的exe加载资源。我已经成功地使用WinApi创建了一个字符串资源,并通过PE explorer、resource Hacker和Hex Editor验证了它们的存在。
我不能通过FindResource找到它们。函数结束,返回一些指针并将LastError设置为0。但是指针b指向无效内存。我尝试用4种不同的方式导入FindResource,结果都是一样的(b1、b2、b3、b4表示每个声明的b)。我发现我需要先加载库,让FindResource找到"一些东西"(a1=a2是两个相同的模块句柄,加载后将精确地指向内存中exe的开头,只是用不同的函数获取)。
我认为a(a=a1=a2)和b必须位于相同的内存空间中(偏移到模块开始?)。但是b和a的差值总是一样的16568。在十六进制编辑器中,我看到我的字符串大约偏移8000,并且在每次创建资源后都会有所不同。我知道可能出了什么问题,但我不确定:
MAKELANGID(0, 0)
~我知道0和0代表中性,我在哪里读到可能有关于*.mui
文件的内容- 资源创造创造了破碎的资源?事实上,两个资源编辑器在显示我的资源时都没有问题
- 进口申报可能是错误的,但我已经尝试了很多可能性,这些都是最好的
- 资源需要打开/锁定/什么
如何成功找到资源?我的代码中有错误吗
public static class MyClass
{
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string fileName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern bool FreeLibrary(IntPtr module);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPStr)] string filename);
[DllImport("kernel32.dll")]
public static extern IntPtr BeginUpdateResource([MarshalAs(UnmanagedType.LPStr)] string filename, bool deleteExistingResources);
[DllImport("kernel32.dll")]
public static extern bool UpdateResource(IntPtr resource, [MarshalAs(UnmanagedType.LPStr)] string type, [MarshalAs(UnmanagedType.LPStr)] string name, ushort language, IntPtr data, uint dataSize);
[DllImport("kernel32.dll")]
public static extern bool EndUpdateResource(IntPtr resource, bool discard);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)]
public static extern IntPtr FindResource1(IntPtr module, [MarshalAs(UnmanagedType.LPStr)]string name, [MarshalAs(UnmanagedType.LPStr)] string type);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)]
public static extern IntPtr FindResource2(IntPtr module, IntPtr name, IntPtr type);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)]
public static extern IntPtr FindResource3(IntPtr module, [In, MarshalAs(UnmanagedType.LPStr)]string name, [In, MarshalAs(UnmanagedType.LPStr)] string type);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "FindResource", SetLastError = true)]
public static extern IntPtr FindResource4(IntPtr module, string lpName, string lpType);
public static ushort MAKELANGID(ushort primaryLanguage, ushort subLanguage)
{
return Convert.ToUInt16((subLanguage << 10) | primaryLanguage);
}
private static void test()
{
string filename1 = "MyApp.exe";
string filename2 = "MyApp2.exe";
//if (!File.Exists(filename2))
{
// creating resource: name = TEST, type = SYSO, lang-id = neutral
File.Copy(filename1, filename2, true);
IntPtr res = BeginUpdateResource(filename2, false);
string s = "aaahello world";
UpdateResource(res, "SYSO", "TEST", MAKELANGID(0, 0), Marshal.StringToHGlobalAnsi(s), (uint) (s.Length));
EndUpdateResource(res, false);
}
// find resource
IntPtr a1 = LoadLibrary(filename2);
IntPtr a2 = GetModuleHandle(filename2);
IntPtr hInstance = Marshal.GetHINSTANCE(typeof(MyClass).Module);
if (a1 == a2)
Console.WriteLine("a1 = a2 = " + a2 + ", hInstance: " + hInstance);
else
Console.WriteLine(a1 + " != " + a2);
for (int i = 0; i < 10; i++)
Console.WriteLine("." + Marshal.ReadByte(a2 + i));
IntPtr b1 = FindResource1(a2, "TEST", "SYSO");
IntPtr b2 = FindResource2(a2, Marshal.StringToHGlobalAnsi("TEST"), Marshal.StringToHGlobalAnsi("SYSO"));
IntPtr b3 = FindResource3(a2, "TEST", "SYSO");
IntPtr b4 = FindResource4(a2, "TEST", "SYSO");
Console.WriteLine(" -> res: " + b1 + ", " + (b1.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b1));
Console.WriteLine(" -> res: " + b2 + ", " + (b2.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b2));
Console.WriteLine(" -> res: " + b3 + ", " + (b3.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b3));
Console.WriteLine(" -> res: " + b4 + ", " + (b4.ToInt32() - a2.ToInt32()) + ", " + Marshal.PtrToStringAnsi(b4));
for (int i = 0; i < 10; i++)
Console.WriteLine("." + Marshal.ReadByte(b1 + i));
}
[STAThread]
public static void Main()
{
test();
Console.ReadKey();
}
}
我知道互联网上有很多关于FindResource的帖子,我读过很多,但没有一个能解决这个问题。
FindResource()
返回一个句柄,而不是指向资源的指针;获取数据还需要几个步骤。您需要先LoadResource()
,然后LockResource()
才能获得指向实际资源字节的指针。
据我所知,这是过去16位时代遗留下来的东西。