在 Windows 上的 Ruby 中检查文件的版本

Checking version of file in Ruby on Windows

提问人: 提问时间:9/17/2008 最后编辑:mikej 更新时间:6/12/2013 访问量:3921

问:

Ruby 中有没有办法找到文件的版本,特别是 .dll 文件?

Ruby 文件 DLL 版本

评论


答:

1赞 cynicalman 9/17/2008 #1

对于任何文件,您都需要发现文件的格式,然后打开文件并读取必要的字节以找出文件的版本。在 Ruby 中没有确定文件版本的 API 或常用方法。

请注意,如果文件版本在文件名中会更容易。

3赞 Erik 9/17/2008 #2

如果你在 Microsoft 平台上工作,你应该能够使用 Ruby 中的 Win32 API 来调用 GetFileVersionInfo(),这将返回你要查找的信息。http://msdn.microsoft.com/en-us/library/ms647003.aspx

12赞 AShelly 9/17/2008 #3

对于 Windows EXE 和 DLL:

require "Win32API"
FILENAME = "c:/ruby/bin/ruby.exe" #your filename here
s=""
vsize=Win32API.new('version.dll', 'GetFileVersionInfoSize', 
                   ['P', 'P'], 'L').call(FILENAME, s)
p vsize
if (vsize > 0)
  result = ' '*vsize
  Win32API.new('version.dll', 'GetFileVersionInfo', 
               ['P', 'L', 'L', 'P'], 'L').call(FILENAME, 0, vsize, result)
  rstring = result.unpack('v*').map{|s| s.chr if s<256}*''
  r = /FileVersion..(.*?)\000/.match(rstring)
  puts "FileVersion = #{r ? r[1] : '??' }"
else
  puts "No Version Info"
end

'unpack'+regexp 部分是一个 hack,“正确”的方式是 VerQueryValue API,但这应该适用于大多数文件。(可能在扩展字符集上惨遭失败。

5赞 Tom Lahti 9/27/2008 #4

如果您想使用 ruby 获取版本信息,但 ruby 代码未在 Windows 上运行,该怎么办?

以下内容就是这样做的(注意相同的扩展字符集警告):

#!/usr/bin/ruby

s = File.read(ARGV[0])
x = s.match(/F\0i\0l\0e\0V\0e\0r\0s\0i\0o\0n\0*(.*?)\0\0\0/)

if x.class == MatchData
  ver=x[1].gsub(/\0/,"")
else
  ver="No version"
end

puts ver
5赞 Pete 6/12/2013 #5

从 Ruby 2.0 开始,该模块已被弃用。以下是 AShelly 使用 Fiddle 回答的更新版本:DL

version_dll = Fiddle.dlopen('version.dll')

s=''
vsize = Fiddle::Function.new(version_dll['GetFileVersionInfoSize'],
            [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
            Fiddle::TYPE_LONG).call(filename, s)

raise 'Unable to determine the version number' unless vsize > 0

result = ' '*vsize
Fiddle::Function.new(version_dll['GetFileVersionInfo'],
                     [Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG,
                      Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP],
        Fiddle::TYPE_VOIDP).call(filename, 0, vsize, result)

rstring = result.unpack('v*').map{|s| s.chr if s<256}*''
r = /FileVersion..(.*?)\000/.match(rstring)

puts r[1]