-
-
Notifications
You must be signed in to change notification settings - Fork 102
Description
New users of this package may find themselves deeply confused when encountering a COMError
.
COMError
is an exception defined in the ctypes
internal implementation, _ctypes
, and is part of the Python standard library. However, it remained undocumented for many years. To address this, I opened an issue and submitted a pull request to add documentation for this error to the official Python documentation.
Another problem with COMError
is that most COM references typically represent error codes as signed 32-bit hexadecimal values, like the ones below, while the error code assigned to its hresult
attribute is an int
, making them less 'googlable'.
Additionally, converting between signed 32-bit hexadecimal strings and integer values requires some extra effort.
For instance, when I was less familiar with HRESULT, I mistakenly tried to derive the integer value for E_NOINTERFACE
using int("0x80004002", 16)
.
To handle these conversions properly, a utility function like the following is necessary:
def signed32bithex_to_int(value: str, /) -> int:
"""
Examples:
>>> from comtypes import hresult as hr
>>> signed32bithex_to_int('0x00000000') == hr.S_OK
True
>>> signed32bithex_to_int('0x00000001') == hr.S_FALSE
True
>>> signed32bithex_to_int('0x8000FFFF') == hr.E_UNEXPECTED
True
"""
val = int(value, 16)
if val < 0x80000000:
return val
return val - 0x100000000
def int_to_signed32bithex(value: int, /) -> str:
"""
Examples:
>>> import comtypes.hresult as hr
>>> int_to_signed32bithex(hr.S_OK)
'0x00000000'
>>> int_to_signed32bithex(hr.S_FALSE)
'0x00000001'
>>> int_to_signed32bithex(hr.E_UNEXPECTED)
'0x8000FFFF'
>>> from comtypes import CoCreateInstance
>>> from comtypes import shelllink, automation
>>> CLSID_ShellLink = shelllink.ShellLink().IPersist_GetClassID()
>>> p = CoCreateInstance(CLSID_ShellLink)
>>> p.QueryInterface(shelllink.IShellLinkA) # doctest: +ELLIPSIS
<POINTER(IShellLinkA) ptr=0x... at ...>
>>> p.QueryInterface(automation.IDispatch) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
_ctypes.COMError: (-2147467262, ..., (None, None, None, 0, None))
>>> int_to_signed32bithex(-2147467262) # E_NOINTERFACE
'0x80004002'
"""
# it is simpler than using `hex(value & 0xFFFFFFFF)`
return f"0x{value & 0xFFFFFFFF:08X}"
For example, let’s consider the case where you encounter an COMError: (-2146233083, ..., ...)
.
Searching for -2146233083
alone will primarily return information about COR_E_TIMEOUT
, which is related to .NET.
However, searching for "0x80131505"
, which can be derived using int_to_signed32bithex(-2146233083)
, makes it easier to find information about UIA_E_TIMEOUT
, which is related to UIAutomation.
I am considering adding such a function to comtypes/hresult.py
with appropriate docstrings.
Doing so will likely reduce the number of inquiries related to error handling in the future, preventing burnout among the community and maintainers.