VerQueryValueW 问题 python 3

VerQueryValueW issue python 3

我正在尝试通过 GetFileVersionInfoSizeW 和 VerQueryValueW 获取文件的版本。我打印了部分版本,但不是全部。它在文件版本的每个字符之间也有一些奇怪的空格。任何人都知道它有什么问题?

我猜这与 python3 的 Unicode 解释有关,因为我不得不从 运行 通常在 python2 中的原始 GetFileVersionInfoSizeA 和 VerQueryValueA 更改 GetFileVersionInfoSizeW 和 VerQueryValueW( ).

import array
from ctypes import *

def get_file_info(filename):
"""
Extract information from a file.
"""
# Get size needed for buffer (0 if no info)
size = windll.version.GetFileVersionInfoSizeW(filename, None)
# If no info in file -> empty string
if not size:
    return 'Failed'
# Create buffer
res = create_string_buffer(size)
# Load file informations into buffer res
windll.version.GetFileVersionInfoW(filename, None, size, res)
r = c_uint()
l = c_uint()
# Look for codepages
windll.version.VerQueryValueW(res, '\VarFileInfo\Translation',
                              byref(r), byref(l))
# If no codepage -> empty string
if not l.value:
    return ''
# Take the first codepage (what else ?)
codepages = array.array('H', string_at(r.value, l.value))
codepage = tuple(codepages[:2].tolist())
# Extract information
windll.version.VerQueryValueW(res, ('\StringFileInfo\%04x%04x\'
+ 'FileVersion') % codepage, byref(r), byref(l))
return string_at(r.value, l.value)

print (get_file_info(r'C:\WINDOWS\system32\calc.exe').decode())

return Microsoft 称之为“Unicode”字符串的功能,但ctypes.wstring 可以转换的实际上是UTF-16LE 编码。 l.value 是 UTF16 字符的计数,而不是字节数,因此请使用以下内容对其进行正确解码。您不需要像现在这样 .decode() 结果。

return wstring_at(r.value, l.value)

这是我的工作代码:

from ctypes import *
from ctypes import wintypes as w

ver = WinDLL('version')
ver.GetFileVersionInfoSizeW.argtypes = w.LPCWSTR, w.LPDWORD
ver.GetFileVersionInfoSizeW.restype = w.DWORD
ver.GetFileVersionInfoW.argtypes = w.LPCWSTR, w.DWORD, w.DWORD, w.LPVOID
ver.GetFileVersionInfoW.restype = w.BOOL
ver.VerQueryValueW.argtypes = w.LPCVOID, w.LPCWSTR, POINTER(w.LPVOID), w.PUINT
ver.VerQueryValueW.restype = w.BOOL

def get_file_info(filename):
    size = ver.GetFileVersionInfoSizeW(filename, None)
    if not size:
        raise RuntimeError('version info not found')
    res = create_string_buffer(size)
    if not ver.GetFileVersionInfoW(filename, 0, size, res):
        raise RuntimeError('GetFileVersionInfoW failed')
    buf = w.LPVOID()
    length = w.UINT()
    # Look for codepages
    if not ver.VerQueryValueW(res, r'\VarFileInfo\Translation', byref(buf), byref(length)):
        raise RuntimeError('VerQueryValueW failed to find translation')
    if length.value == 0:
        raise RuntimeError('no code pages')
    codepages = array.array('H', string_at(buf.value, length.value))
    codepage = tuple(codepages[:2])
    # Extract information
    if not ver.VerQueryValueW(res, rf'\StringFileInfo\{codepage[0]:04x}{codepage[1]:04x}\FileVersion', byref(buf), byref(length)):
        raise RuntimeError('VerQueryValueW failed to find file version')
    return wstring_at(buf.value,length.value)

print(get_file_info(r'c:\windows\system32\calc.exe'))

输出:

10.0.19041.1 (WinBuild.160101.0800)