C'è un modo in Ruby per trovare la versione di un file, in particolare un file .dll?Controllo della versione del file in Ruby su Windows
risposta
Per qualsiasi file, è necessario scoprire in che formato si trova il file, quindi aprire il file e leggere i byte necessari per individuare la versione del file. Non esiste un'API o un metodo comune per determinare una versione del file in Ruby.
Si noti che sarebbe più semplice se la versione del file fosse nel nome del file.
Se si sta lavorando sulla piattaforma Microsoft, si dovrebbe essere in grado di utilizzare l'API Win32 in Ruby per chiamare GetFileVersionInfo(), che restituirà le informazioni che state cercando. http://msdn.microsoft.com/en-us/library/ms647003.aspx
Per Windows EXE e 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
Il 'decomprimere' + parte regexp è un hack, il modo "corretto" è l'API VerQueryValue, ma questo dovrebbe funzionare per la maggior parte dei file. (probabilmente fallisce miseramente su set di caratteri estesi.)
Cosa succede se si desidera ottenere le informazioni sulla versione con ruby, ma il codice ruby non è in esecuzione su Windows?
Quanto segue fa proprio questo (badare lo stesso avvertimento esteso set di caratteri):
#!/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
Come di Ruby 2.0, il modulo DL
è deprecato. Ecco una versione aggiornata della risposta di AShelly, utilizzando 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]