(见底部编辑)
使用EnumResourceNames,我试图在我自己的dll中找到存储为资源的图标。这是整个DLL代码:
library focusRes;
{$R focusResResource.res} // contains the icons I need to load
{$R *.res}
begin
end.
我可以使用LoadLibrary和LoadLibraryEx(已验证)正确加载dll。但是对EnumResourceNames的调用返回false,而GetLastError返回998(对内存位置的无效访问)。调用代码是:
hdll := LoadLibraryEx( PChar( DLLFilename ), 0, LOAD_LIBRARY_AS_DATAFILE );
// OR: hdll := LoadLibrary( PChar( DLLFilename ));
enumResult := EnumResourceNames( hDll, RT_ICON, @EnumResFlags, 0 );
// (hDll is the handle returned from LoadLibrary)
和回调函数:
function EnumResFlags( hDll : HMODULE; ResType, ResName : PChar;
notUsed : pointer ) : integer; stdcall;
begin
// NEVER GETS CALLED
// log( ResName);
result := 1; // continue enumeration
end;
回调是一个独立的函数(不是对象方法或本地函数)。
在我的调查中,我发现了一些令人困惑的线索:
问题似乎与我的dll有关,因为如果我替换随机 来自第三方应用程序的DLL,问题就消失了。
我的dll问题似乎不,因为我可以打开它 在第三方图标编辑器中,以及存储在dll中的所有图标都是 正确加载。
当我尝试为特定图标名称创建资源流时, 异常是“未找到资源[名称]”。 (但图标编辑器发现没问题)
(Windows 7 32位上的Delphi XE)
编辑1:创建一个新的Delphi项目并在其中加入以下行:
enumResult := EnumResourceNames( hInstance, RT_ICON, @EnumCallback, 0 );
结果:错误998.将RT_ICON更改为其他内容,例如RT_RTCDATA,问题就消失了。
编辑2 如果我没有在回调中引用ResName参数,则问题不会发生。 (如果我在回调中只说“结果:= 1”,则没有错误。)返回Delphi 3(!)并得到相同的确切结果,因此它并不特定于XE。如果我尝试枚举RT_RCDATA而不是RT_ICON,则没有问题,我可以读取ResName。
答案 0 :(得分:8)
您未正确解析回调的lpszType
和lpszName
参数。您的测试失败涉及将资源ID传递给您的回调,而不是资源名称。当您尝试通过指针访问进程内存的第一个64kb时,它是无效的内存访问。
您需要测试ResType
/ ResName
是否为名称或ID,然后对其进行相应处理,如下所示:
function EnumResFlags( hDll : HMODULE; ResType, ResName : PChar; notUsed : pointer ) : integer; stdcall;
begin
if IS_INTRESOURCE(ResName) then
log(IntToStr(Integer(ResName)))
else
log(ResName);
...
end;
如果您的Delphi版本没有定义IS_INTRESOURCE()
,您可以手动定义它:
function IS_INTRESOURCE(lpszType: PChar): BOOL;
begin
Result := ULONG_PTR(lpszType) shr 16 = 0;
end;