我想从外部 EXE 文件加载 VERSION 资源的二进制数据。这应该相当简单:
var
hFile: HMODULE; // File=image to load
hR: HRSRC; // Resource handle
hG: HGLOBAL; // Loaded resource
p: Pointer; // Actual accessible data to the resource
sDebug: AnsiString;
sFile: Widestring;
begin
// Commonly known to every Windows installation, 32-bit version.
sFile:= 'C:\Windows\SysWOW64\calc.exe';
// WinAPI and https://stackoverflow.com/a/23035857/4299358 want both flags.
hFile:= LoadLibraryExW( PWideChar(sFile), 0, LOAD_LIBRARY_AS_DATAFILE or LOAD_LIBRARY_AS_IMAGE_RESOURCE );
// 2nd param=resource name/ID; 3rd param=resource type. Unlike FindResourceExA() where these are swapped.
hR:= FindResourceA( hFile, PAnsiChar('#1'), PAnsiChar('#16') );
// Same results as above: returns valid handle. Just another valid way of wanting numeric IDs.
{hR:= FindResourceA( hFile, PAnsiChar(1), PAnsiChar(16) );}
// Both succeed in returning a valid handle and a non-empty pointer.
hG:= LoadResource( hFile, hR );
p:= LockResource( hR );
// AnsiString will have the bytes $f0 $b2 $0b $00 $84 $03 $00, but not the
// expected $bd $04 $ef $fe from VS_FIXEDFILEINFO.dwSignature after about 40 bytes.
SetString( sDebug, PAnsiChar(p), 50 );
我一直得到有效的句柄,还有一个非
nil
指针。出于调试目的,我将字节填充到 AnsiString
中,然后查看其内容。如果我在文件中搜索这些字节,我会发现它们距离我想要的资源(文件位置 $585c0)很远 - 而且这是这些字节的唯一出现:
我想要的
VS_VERSION_INFO
资源后来在 $b96f0 处找到了 388 KiB(人们甚至可以发现存储 PNG 文件的前一个资源 - 请注意 IEND
块,很可能是它的图标之一)。 40 个字节后可以看到来自 $bd $04 $ef $fe
的预期字节 VS_FIXEDFILEINFO.dwSignature
:
这也得到了 Resource Hacker 的证实,显示了资源在二进制文件中的位置(请参阅文件位置为“B96F0”的状态栏) - 它还确认资源的名称为
1
(与许多其他资源一样)并且是唯一的 VERSION
资源,所以我不会意外地找到不同的资源:
LockResource()
清楚地解释了:
返回值是指向资源第一个字节的指针
VS_FIXEDFILEINFO
结构,它应该位于 VS_VERSIONINFO
伪结构 的 38 字节之后(3 WORD
s + 15 WCHAR
s = 36 字节,至少带有可变填充) ).
我不想想要使用
GetFileVersionInfoW()
和VerQueryValueW()
,因为我想避免Windows成为中间人并且因为文件版本只是一步 - 我的目标是阅读任何资源可靠(不仅仅是那些 WinAPI 提供辅助函数的情况)。
我在Windows 7x64上使用Delphi 7,因此调试的EXE是32位的,并且加载的CALC.EXE也确保是32位的(尽管这不重要)。我也无法访问其他 32 位 EXE 文件的版本资源的预期字节。
您向
LockResource()
传递了错误的参数。您应该通过 hG
而不是 hR
。