windows - ruby win32api & 结构 (VerQueryValue)

标签 windows ruby winapi

我正在尝试调用标准 Win32 API 函数来获取文件版本信息,使用 win32-api library .

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.

最佳答案

这是我开始工作的完整代码,以防其他人正在寻找这样的功能。

返回一个包含产品/文件版本号四部分的数组(即 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

关于windows - ruby win32api & 结构 (VerQueryValue),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2219486/

相关文章:

java - 如何通知用户桌面应用程序的重要事件?

c# - 在 C# 中如何将 IP 地址字符串解析为 uint 值?

python - Windows 中的临时 PYTHONPATH

c++ - 如何在C++中进行无限循环? ( Windows )

windows - 如何在 Windows 上的 powershell 上执行 sudo

无法打开 Windows 命名管道进行写入?

ruby - 在 OS X 10.8.1 上安装 Ruby 1.9.3 时出错

sql - 使用 UNION 查询从 ODBC 源中检索多行

ruby - Ruby 中的符号是用构造函数还是初始化函数创建的?

ruby - 使用类作为整个文件的命名空间