(请参阅底部的编辑)
使用 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中存储的所有图标都是 正确加载。
当我尝试为特定图标名称创建资源流时, 异常(exception)是“未找到资源[名称]”。 (但是图标编辑器觉得还好)
(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。
最佳答案
您没有正确解析回调的 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;
关于delphi - EnumResourceNames 返回 Windows 错误 998(对内存位置的访问无效),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23024402/