Я пытаюсь назвать стандартные API-функции Win32 для получения информации о версии файла, пользуясь библиотекой win32-api.
3 функциями version.dll является GetFileVersionInfoSize, GetFileVersionInfo и VerQueryValue. Затем я называю RtlMoveMemory в kernel32.dll для получения копии структуры 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.
Это полный код, который я должен выполнить, на случай, если другие ищут такую функцию.
Возвращает массив с четырьмя частями номера версии продукта / файла (т. Е. То, что называется «Версия файла» в окне свойств файла dll):
def file_version ref, options = {}
options = {:path => LIBDIR, :extension => 'dll'}.merge(options)
begin
file = File.join(ROOT, options[:path],"#{ref}.#{options[:extension]}").gsub(/\//,"\\")
buf = [0].pack('L')
version_size = GetFileVersionInfoSize.call(file + "\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
fixed_info = Array.new(18,0).pack('LSSSSSSSSSSLLLLLLL')
RtlMoveMemory.call(fixed_info, addr.unpack('L')[0], fixed_info.length)
fixed_info.unpack('LSSSSSSSSSSLLLLLLL')[5..8].reverse
rescue
[]
end
end