dimanche 4 mai 2014

Vérification de version du fichier en Ruby sous Windows - Stack Overflow


Is there a way in Ruby to find the version of a file, specifically a .dll file?




For Windows EXE's and DLL's:


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

The 'unpack'+regexp part is a hack, the "proper" way is the VerQueryValue API, but this should work for most files. (probably fails miserably on extended character sets.)




What if you want to get the version info with ruby, but the ruby code isn't running on Windows?


The following does just that (heeding the same extended charset warning):


#!/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



If you are working on the Microsoft platform, you should be able to use the Win32 API in Ruby to call GetFileVersionInfo(), which will return the information you're looking for. http://msdn.microsoft.com/en-us/library/ms647003.aspx




For any file, you'd need to discover what format the file is in, and then open the file and read the necessary bytes to find out what version the file is. There is no API or common method to determine a file version in Ruby.


Note that it would be easier if the file version were in the file name.




As of Ruby 2.0, the DL module is deprecated. Here is an updated version of AShelly's answer, using Fiddle:


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]


Is there a way in Ruby to find the version of a file, specifically a .dll file?



For Windows EXE's and DLL's:


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

The 'unpack'+regexp part is a hack, the "proper" way is the VerQueryValue API, but this should work for most files. (probably fails miserably on extended character sets.)



What if you want to get the version info with ruby, but the ruby code isn't running on Windows?


The following does just that (heeding the same extended charset warning):


#!/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


If you are working on the Microsoft platform, you should be able to use the Win32 API in Ruby to call GetFileVersionInfo(), which will return the information you're looking for. http://msdn.microsoft.com/en-us/library/ms647003.aspx



For any file, you'd need to discover what format the file is in, and then open the file and read the necessary bytes to find out what version the file is. There is no API or common method to determine a file version in Ruby.


Note that it would be easier if the file version were in the file name.



As of Ruby 2.0, the DL module is deprecated. Here is an updated version of AShelly's answer, using Fiddle:


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]

0 commentaires:

Enregistrer un commentaire