我試圖調用標準的Win32 API函數來獲取文件版本信息,使用win32-api library。ruby win32api&structs(VerQueryValue)
3 version.dll函數是GetFileVersionInfoSize,GetFileVersionInfo和VerQueryValue。然後我調用kernel32.dll中的RtlMoveMemory來獲取VS_FIXEDFILEINFO結構的副本(請參閱Microsoft文檔:http://msdn.microsoft.com/en-us/library/ms646997%28VS.85%29.aspx
)。
我畫了一個例子,我看到使用VB:http://support.microsoft.com/kb/139491
。
我的問題是,最終返回的數據似乎不符合預期的結構,事實上它甚至不會返回一致的值。我懷疑數據在某些時候會受到損壞,可能是VerQueryValue或RtlMoveMemory。
下面是代碼:
GetFileVersionInfoSize = Win32::API.new('GetFileVersionInfoSize','PP','I','version.dll')
GetFileVersionInfo = Win32::API.new('GetFileVersionInfo','PIIP','I', 'version.dll')
VerQueryValue = Win32::API.new('VerQueryValue','PPPP','I', 'version.dll')
RtlMoveMemory = Win32::API.new('RtlMoveMemory', 'PPI', 'V', 'kernel32.dll')
buf = [0].pack('L')
version_size = GetFileVersionInfoSize.call(myfile + "\0", buf)
raise Exception.new if version_size == 0 #TODO
version_info = 0.chr * version_size
version_ok = GetFileVersionInfo.call(file, 0, version_size, version_info)
raise Exception.new if version_ok == 0 #TODO
addr = [0].pack('L')
size = [0].pack('L')
query_ok = VerQueryValue.call(version_info, "\\\0", addr, size)
raise Exception.new if query_ok == 0 #TODO
# note that at this point, size == 4 -- is that right?
fixed_info = Array.new(13,0).pack('L*')
RtlMoveMemory.call(fixed_info, addr, fixed_info.length)
# fixed_info.unpack('L*') #=> seemingly random data, usually only the first two dwords' worth and the rest 0.
我想我想通了..基本上VerQueryValue返回一個指針的指針(上面的變量地址),而RtlMoveMemory想要一個指針,即久,地址引用。 所以我改變了聲明: RtlMoveMemory =的Win32 :: API.new( 'RtlMoveMemory', 'PLI', 'V', 'KERNEL32.DLL') ,然後調用它: RtlMoveMemory.call( fixed_info,addr.unpack('L')[0],fixed_info.length) – 2010-02-08 04:55:53