2017-03-05 15 views
0

私はGetFileVersionInfoSizeWとVerQueryValueWでファイルのバージョンを取得しようとしています。私はバージョンの一部を印刷しましたが、全部ではありません。また、ファイルバージョンの各文字の間にいくつかの奇妙なスペースがあります。誰でもそれが間違っているという考えを持っていますか?VerQueryValueW issue python 3

Python3のUnicode解釈に関連していると思います。元のGetFileVersionInfoSizeAとVerQueryValueAからPython2(https://stackoverflow.com/a/38924793/7144869)で正常に実行された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()) 
+0

私はこのコードを実行すると、私はエラー「OSErrorの:例外:0x0000000016F42058読み込みアクセス違反」を取得進値がない有効なメモリポインタかのようにRに対応しています。この行では失敗しますcodepages = array.array( 'H'、string_at(r.value、l.value))。私はAsciiを使ってPython2のバージョンを動かすことができますが、私の人生の中では、このコードはPython3でも使えるようになります。あなたが完全に機能するコードを投稿することができればそれは素晴らしいものです。 – user1024792

+0

これは、上のものと同じですが、リターンであなたはします: 'return wstring_at(r.value、l.value)' –

+0

どのバージョンのPython 3で?私は3.5と3.6といくつかの異なるマシン上でテストし、codepages = array.array( 'H'、string_at(r.value、l.value))行のすべてのシステムでメモリアクセス違反を取得します。あなたはなにか考えはありますか?別の何かがなければならない、私はちょうどそれが何であるか見ることができない。 – user1024792

答えて

0

機能は、Microsoftが「ユニコード」の文字列と呼ぶものを返すが、実際にエンコードされたUTF-16LE ctypes.wstringを変換することができるということです。 l.valueはバイトではなくUTF16文字の数ですので、正しくデコードするには以下を使用してください。あなたは今行っているので結果は.decode()になる必要はありません。

return wstring_at(r.value, l.value) 
+0

ありがとう@マークトローネンこれらの種類のエンコード/デコードは時々本当に混乱している。しかし簡単な質問ですが、どのように関数について知っていましたかwstring_at()Pythonでctypesについて読むことができるオンラインリファレンスがありますか? –

+0

@IkerHua ctypesライブラリには、docs.python.orgに関する優れたドキュメントがあります。 'dir(ctypes)'もそれを表示し、 'help(ctypes.wstring_at)'はそれを記述します。 –