Reputation: 515
I am trying to execute windll.version.GetFileVersionInfoSizeA()
in python ctypes
. I am executing the below code:
_GetFileVersionInfoSizeA = ctypes.windll.version.GetFileVersionInfoSizeA
_GetFileVersionInfoSizeA.argtypes = [ctypes.c_char_p, ctypes.c_void_p]
_GetFileVersionInfoSizeA.restype = ctypes.c_uint32
_GetFileVersionInfoSizeA.errcheck = RaiseIfZero # RaiseIfZero is a function to raise error
# lptstrFilename is the file path
dwLen = _GetFileVersionInfoSizeA(lptstrFilename, None)
This code works perfectly in python 2, but it's not working in python 3.8. It gives the following error:
argument 1: <class 'TypeError'>: wrong type
According to msdn doc for GetFileVersionInfoSizeA
, the second argument should be:
"A pointer to a variable that the function sets to zero."
I tried the following code, but it gives the same error as before.
dwLen = _GetFileVersionInfoSizeA(lptstrFilename, LPVOID)
I am not sure what am I missing.
Note - This is my first time using ctypes
.
Upvotes: 1
Views: 745
Reputation: 178179
In Python 3 strings are Unicode by default. Even in Python 2 its best to use Unicode strings, and therefore the W versions of Windows APIs, which are natively Unicode. So to call that API strictly according to documentation:
>>> from ctypes import *
>>> from ctypes import wintypes as w
>>> dll = WinDLL('api-ms-win-core-version-l1-1-0')
>>> GetFileVersionInfoSize = dll.GetFileVersionInfoSizeW
>>> GetFileVersionInfoSize.argtypes = w.LPCWSTR,w.LPDWORD
>>> GetFileVersionInfoSize.restype = w.DWORD
>>> GetFileVersionInfoSize('test.exe',byref(w.DWORD())) # create a temporary DWORD passed by reference.
2316
Note that the second parameter is not documented to accept nullptr(a.k.a None
in Python) so it should be a valid reference.
To call the ANSI(A) version of the function pass a byte string encoded correctly in the default ANSI encoding e.g. 'test.exe'.encode('ansi')
, but note that non-ASCII filenames will cause trouble that is mitigated by using the Unicode(W) version.
Upvotes: 0
Reputation: 24907
In python2 two types could be used to represent strings. strings and Unicode strings. Hence c_char_p
ctypes type is used to represent the python2 string type and c_wchar_p
ctypes type is used to represent the python2 unicode string type.
But in python3 there is only one string type. Hence c_wchar_p
ctypes type is used to represent the python3 string
type and c_char_p
ctypes type is used to represent the python3 bytes
type.
You can find the Fundamental data types in python 2
and python 3
documentation.
So you could do
dwLen = _GetFileVersionInfoSizeA(your_file_name.encode(), None)
Upvotes: 1