Umang Agrawal
Umang Agrawal

Reputation: 515

Executing windll.version.GetFileVersionInfoSizeA() fails in Python 3

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

Answers (2)

Mark Tolonen
Mark Tolonen

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

user459872
user459872

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

Related Questions