我最近使用二级库/二进制模块的资源,遇到了一个奇怪的错误。
我有两个原生的WinAPI引用:
[DllImport("kernel32.dll", SetLastError = true)]
public extern static bool EnumResourceNames(IntPtr hModule, int lpszType, EnumResNameProc lpEnumFunc, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError=true)]
public extern static IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, int dwFlags);
当我调用LoadLibraryEx时,我正在获取IntPtr实例 - 正是我需要的:
IntPtr x = WinApi.LoadLibraryEx(@"D:\Software\Reflector\Reflector.exe",IntPtr.Zero,2);
Debug.WriteLine(x.ToInt32());
但是,当我尝试枚举图标资源(由ID = 3定义)时:
Debug.WriteLine(WinApi.EnumResourceNames(x, 3, new EnumResNameProc(ListCallback), IntPtr.Zero));
Debug.WriteLine(Marshal.GetLastWin32Error());
我收到此错误代码(由GetLastError返回):
-532462766
据我所知,这通常意味着存在未知错误,但我只是好奇 - 从可执行文件中列出资源可能会出现什么问题?
答案 0 :(得分:4)
-532462766 == 0xe0434352。最后三个十六进制对拼写“CCR”,这是Microsoft程序员用来尝试提出易于识别的异常代码的常用技巧。确切的含义是非常神秘的,除了它通常与托管代码相关联,并且在子系统中看起来非常低级,通常不会产生有意义的托管异常。
这个神秘异常有一个很好的候选理由,你的EnumResources pinvoke声明是错误的。第二个参数是IntPtr,而不是int。这有可能在64位操作系统上运行kaboom。
如果您弄清楚CCR的含义,请回复。
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Diagnostics;
class Program {
static void Main(string[] args) {
try {
IntPtr module = LoadLibraryEx(@"C:\windows\system32\user32.dll", IntPtr.Zero, 2);
if (module == IntPtr.Zero) throw new Win32Exception();
if (!EnumResourceNames(module, (IntPtr)3, new EnumResNameProc(ListCallback), IntPtr.Zero))
throw new Win32Exception();
}
catch (Win32Exception ex) {
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
static bool ListCallback(IntPtr hModule, IntPtr type, IntPtr name, IntPtr lp) {
long idorname = (long)name;
if (idorname >> 16 == 0) Console.WriteLine("#{0}", idorname);
else Console.WriteLine(Marshal.PtrToStringAnsi(name));
return true;
}
public delegate bool EnumResNameProc(IntPtr hModule, IntPtr type, IntPtr name, IntPtr lp);
[DllImport("kernel32.dll", SetLastError = true)]
public extern static bool EnumResourceNames(IntPtr hModule, IntPtr type, EnumResNameProc lpEnumFunc, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true)]
public extern static IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, int dwFlags);
}
答案 1 :(得分:0)
Hans Passant说得对,但要详细说明错误消息,0xe0434352是.NET异常的通用错误代码。如果从Visual Studio调试器运行此命令,当EnumResourceNames尝试调用回调时,您将看到正在引发System.ArgumentException
。错误消息是:
作为String传入的指针不能位于进程地址空间的底部64K。
此异常被EnumResourceNames捕获并变为失败。正如Hans所示,解决方案是回调函数必须将第二个和第三个参数作为IntPtr而不是字符串。