使用 ctypes 调用 EnumRunning 方法时出现 ValueError 异常 "Procedure probably called with not enough arguments (4 bytes missing)"
ValueError exception "Procedure probably called with not enough arguments (4 bytes missing)" when calling the EnumRunning method using ctypes
在 Python 我正在尝试调用 Windows API EnumRunning
method of the IRunningObjectTable
interface that I get from the GetRunningObjectTable
function using the comtypes
and ctypes
modules (I want to avoid using other non-standard modules such as pythoncom
).
我主要是从C:\Program Files\Windows Kits\Include.0.17763.0\um
中的moniker.py
and persist.py
and the objbase.h
header file页面中检索和修改代码。
当我尝试调用 EnumRunning
方法时,引发了 ValueError
异常:
Procedure probably called with not enough arguments (4 bytes missing)
异常消息来自文件 _ctypes.pyd
,因为如果我在文件中修改它,它确实会发生变化,但我无法阅读其中包含的已编译 Python 代码来尝试理解原因正在筹集中。
ValueError
异常的文档是:
Raised when an operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as IndexError.
所以问题可能出在我从 GetRunningObjectTable
函数获得的 IRunningObjectTable
接口的值上。虽然函数确实 return HRESULT
S_OK
value 所以我不确定。
我已经搜索了异常消息,但我得到的信息是关于调用约定的,并且缺少一些参数,我已经检查过但似乎并非如此。
如果我尝试用另一个参数调用它,我会得到 TypeError
异常:
this function takes 1 argument (2 given)
只有一个参数,所以顺序是正确的,尝试使用 cdll
或 oledll
而不是 windll
也没有用。
代码如下:
from comtypes import GUID, IUnknown, STDMETHOD
from ctypes import byref, c_void_p, HRESULT, POINTER, Structure, windll
from ctypes.wintypes import BOOL, DWORD, FILETIME, LARGE_INTEGER, LPCVOID, LPOLESTR, ULARGE_INTEGER, ULONG
CLSID = GUID
IID = GUID
REFIID = POINTER(IID)
class STATSTG(Structure):
_fields_ = [
('pwcsName', LPOLESTR),
('type', DWORD),
('cbSize', ULARGE_INTEGER),
('mtime', FILETIME),
('ctime', FILETIME),
('atime', FILETIME),
('grfMode', DWORD),
('grfLocksSupported', DWORD),
('clsid', CLSID),
('grfStateBits', DWORD),
('reserved', DWORD)]
class BIND_OPTS(Structure):
_fields_ = [
('cbStruct', DWORD),
('grfFlags', DWORD),
('grfMode', DWORD),
('dwTickCountDeadline', DWORD)]
class IEnumString(IUnknown):
_iid_ = GUID('{00000101-0000-0000-C000-000000000046}')
class ISequentialStream(IUnknown):
_iid_ = GUID('{0c733a30-2a1c-11ce-ade5-00aa0044773d}')
_methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Read', [c_void_p, ULONG, POINTER(ULONG)]),
STDMETHOD(HRESULT, 'Write', [LPCVOID, ULONG, POINTER(ULONG)])]
class IStream(ISequentialStream):
_iid_ = GUID('{0000000C-0000-0000-C000-000000000046}')
_methods_ = IUnknown._methods_
class IEnumMoniker(IUnknown):
_iid_ = GUID('{00000102-0000-0000-C000-000000000046}')
class IBindCtx(IUnknown):
_iid_ = GUID('{0000000E-0000-0000-C000-000000000046}')
class IRunningObjectTable(IUnknown):
_iid_ = GUID('{00000010-0000-0000-C000-000000000046}')
class IPersist(IUnknown):
_iid_ = GUID('{0000010C-0000-0000-C000-000000000046}')
_methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'GetClassID', [POINTER(GUID)])]
class IPersistStream(IPersist):
_iid_ = GUID('{00000109-0000-0000-C000-000000000046}')
_methods_ = IPersist._methods_ + [
STDMETHOD(HRESULT, 'IsDirty'),
STDMETHOD(HRESULT, 'Load', [POINTER(IStream)]),
STDMETHOD(HRESULT, 'Save', [POINTER(IStream), BOOL]),
STDMETHOD(HRESULT, 'GetSizeMax', [POINTER(ULARGE_INTEGER)])]
class IMoniker(IPersistStream):
_iid_ = GUID('{0000000F-0000-0000-C000-000000000046}')
IEnumString._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Next', [ULONG, POINTER(LPOLESTR), POINTER(ULONG)]),
STDMETHOD(HRESULT, 'Skip', [ULONG]),
STDMETHOD(HRESULT, 'Reset'),
STDMETHOD(HRESULT, 'Clone', [POINTER(POINTER(IEnumString))])]
IStream._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Seek', [LARGE_INTEGER, DWORD, POINTER(ULARGE_INTEGER)]),
STDMETHOD(HRESULT, 'SetSize', [ULARGE_INTEGER]),
STDMETHOD(HRESULT, 'CopyTo', [ULARGE_INTEGER, ULARGE_INTEGER, POINTER(ULARGE_INTEGER)]),
STDMETHOD(HRESULT, 'Commit', [DWORD]),
STDMETHOD(HRESULT, 'Revert'),
STDMETHOD(HRESULT, 'LockRegion', [ULARGE_INTEGER, ULARGE_INTEGER, DWORD]),
STDMETHOD(HRESULT, 'UnlockRegion', [ULARGE_INTEGER, ULARGE_INTEGER, DWORD]),
STDMETHOD(HRESULT, 'Stat', [POINTER(STATSTG), DWORD]),
STDMETHOD(HRESULT, 'Clone', [POINTER(POINTER(IStream))])]
IEnumMoniker._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Next', [ULONG, POINTER(POINTER(IMoniker)), POINTER(ULONG)]),
STDMETHOD(HRESULT, 'Skip', [ULONG]),
STDMETHOD(HRESULT, 'Reset'),
STDMETHOD(HRESULT, 'Clone', [POINTER(POINTER(IEnumMoniker))])]
IBindCtx._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'RegisterObjectBound', [POINTER(IUnknown)]),
STDMETHOD(HRESULT, 'RevokeObjectBound', [POINTER(IUnknown)]),
STDMETHOD(HRESULT, 'ReleaseBoundObjects'),
STDMETHOD(HRESULT, 'SetBindOptions', [POINTER(BIND_OPTS)]),
STDMETHOD(HRESULT, 'GetBindOptions', [POINTER(BIND_OPTS)]),
STDMETHOD(HRESULT, 'GetRunningObjectTable', [POINTER(POINTER(IRunningObjectTable))]),
STDMETHOD(HRESULT, 'RegisterObjectParam', [LPOLESTR, POINTER(IUnknown)]),
STDMETHOD(HRESULT, 'GetObjectParam', [LPOLESTR, POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'EnumObjectParam', [POINTER(POINTER(IEnumString))]),
STDMETHOD(HRESULT, 'RevokeObjectParam', [LPOLESTR])]
IRunningObjectTable._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Register', [DWORD, POINTER(IUnknown), POINTER(IMoniker), POINTER(DWORD)]),
STDMETHOD(HRESULT, 'Revoke', [DWORD]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetObject', [POINTER(IMoniker), POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'NoteChangeTime', [DWORD, POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'EnumRunning', [POINTER(POINTER(IEnumMoniker))])]
IMoniker._methods_ = IPersistStream._methods_ + [
STDMETHOD(HRESULT, 'BindToObject', [POINTER(IBindCtx), POINTER(IMoniker), REFIID, POINTER(c_void_p)]),
STDMETHOD(HRESULT, 'BindToStorage', [POINTER(IBindCtx), POINTER(IMoniker), REFIID, POINTER(c_void_p)]),
STDMETHOD(HRESULT, 'Reduce', [POINTER(IBindCtx), DWORD, POINTER(POINTER(IMoniker)), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'ComposeWith', [POINTER(IMoniker), BOOL, POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'Enum', [BOOL, POINTER(POINTER(IEnumMoniker))]),
STDMETHOD(HRESULT, 'IsEqual', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'Hash', [POINTER(DWORD)]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IBindCtx), POINTER(IMoniker), POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IBindCtx), POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'Inverse', [POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'CommonPrefixWith', [POINTER(IMoniker), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'RelativePathTo', [POINTER(IMoniker), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'GetDisplayName', [POINTER(IBindCtx), POINTER(IMoniker), POINTER(LPOLESTR)]),
STDMETHOD(HRESULT, 'ParseDisplayName', [POINTER(IBindCtx), POINTER(IMoniker), LPOLESTR, POINTER(ULONG), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'IsSystemMoniker', [POINTER(DWORD)])]
S_OK = 0
RunningObjectTable = POINTER(IRunningObjectTable)()
GetRunningObjectTable = windll.ole32.GetRunningObjectTable
GetRunningObjectTable.argtypes = [DWORD, POINTER(POINTER(IRunningObjectTable))]
GetRunningObjectTable.restype = HRESULT
if GetRunningObjectTable(0, byref(RunningObjectTable)) != S_OK:
raise Exception('GetRunningObjectTable failed.')
EnumMoniker = POINTER(IEnumMoniker)()
try:
RunningObjectTable.EnumRunning(byref(EnumMoniker))
except ValueError as exception:
print(exception)
input()
我找到了 NV Access 的 NVDA(非可视化桌面访问)GitHub 存储库,其中的文件 objidl.py
包含了它们的实现,并且在一点一点地修改我的实现方式之后,我发现问题是我将 IUnknown._methods_
添加到每个接口的方法中。
所以不要像这样声明方法:
IRunningObjectTable._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Register', [DWORD, POINTER(IUnknown), POINTER(IMoniker), POINTER(DWORD)]),
STDMETHOD(HRESULT, 'Revoke', [DWORD]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetObject', [POINTER(IMoniker), POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'NoteChangeTime', [DWORD, POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'EnumRunning', [POINTER(POINTER(IEnumMoniker))])]
我应该这样声明它们:
IRunningObjectTable._methods_ = [
STDMETHOD(HRESULT, 'Register', [DWORD, POINTER(IUnknown), POINTER(IMoniker), POINTER(DWORD)]),
STDMETHOD(HRESULT, 'Revoke', [DWORD]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetObject', [POINTER(IMoniker), POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'NoteChangeTime', [DWORD, POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'EnumRunning', [POINTER(POINTER(IEnumMoniker))])]
(我编辑了答案,因为起初我认为解决问题的方法是使用 COMMETHOD
函数而不是 STDMETHOD
函数,但现在发现情况并非如此全部)
在 Python 我正在尝试调用 Windows API EnumRunning
method of the IRunningObjectTable
interface that I get from the GetRunningObjectTable
function using the comtypes
and ctypes
modules (I want to avoid using other non-standard modules such as pythoncom
).
我主要是从C:\Program Files\Windows Kits\Include.0.17763.0\um
中的moniker.py
and persist.py
and the objbase.h
header file页面中检索和修改代码。
当我尝试调用 EnumRunning
方法时,引发了 ValueError
异常:
Procedure probably called with not enough arguments (4 bytes missing)
异常消息来自文件 _ctypes.pyd
,因为如果我在文件中修改它,它确实会发生变化,但我无法阅读其中包含的已编译 Python 代码来尝试理解原因正在筹集中。
ValueError
异常的文档是:
Raised when an operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as IndexError.
所以问题可能出在我从 GetRunningObjectTable
函数获得的 IRunningObjectTable
接口的值上。虽然函数确实 return HRESULT
S_OK
value 所以我不确定。
我已经搜索了异常消息,但我得到的信息是关于调用约定的,并且缺少一些参数,我已经检查过但似乎并非如此。
如果我尝试用另一个参数调用它,我会得到 TypeError
异常:
this function takes 1 argument (2 given)
只有一个参数,所以顺序是正确的,尝试使用 cdll
或 oledll
而不是 windll
也没有用。
代码如下:
from comtypes import GUID, IUnknown, STDMETHOD
from ctypes import byref, c_void_p, HRESULT, POINTER, Structure, windll
from ctypes.wintypes import BOOL, DWORD, FILETIME, LARGE_INTEGER, LPCVOID, LPOLESTR, ULARGE_INTEGER, ULONG
CLSID = GUID
IID = GUID
REFIID = POINTER(IID)
class STATSTG(Structure):
_fields_ = [
('pwcsName', LPOLESTR),
('type', DWORD),
('cbSize', ULARGE_INTEGER),
('mtime', FILETIME),
('ctime', FILETIME),
('atime', FILETIME),
('grfMode', DWORD),
('grfLocksSupported', DWORD),
('clsid', CLSID),
('grfStateBits', DWORD),
('reserved', DWORD)]
class BIND_OPTS(Structure):
_fields_ = [
('cbStruct', DWORD),
('grfFlags', DWORD),
('grfMode', DWORD),
('dwTickCountDeadline', DWORD)]
class IEnumString(IUnknown):
_iid_ = GUID('{00000101-0000-0000-C000-000000000046}')
class ISequentialStream(IUnknown):
_iid_ = GUID('{0c733a30-2a1c-11ce-ade5-00aa0044773d}')
_methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Read', [c_void_p, ULONG, POINTER(ULONG)]),
STDMETHOD(HRESULT, 'Write', [LPCVOID, ULONG, POINTER(ULONG)])]
class IStream(ISequentialStream):
_iid_ = GUID('{0000000C-0000-0000-C000-000000000046}')
_methods_ = IUnknown._methods_
class IEnumMoniker(IUnknown):
_iid_ = GUID('{00000102-0000-0000-C000-000000000046}')
class IBindCtx(IUnknown):
_iid_ = GUID('{0000000E-0000-0000-C000-000000000046}')
class IRunningObjectTable(IUnknown):
_iid_ = GUID('{00000010-0000-0000-C000-000000000046}')
class IPersist(IUnknown):
_iid_ = GUID('{0000010C-0000-0000-C000-000000000046}')
_methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'GetClassID', [POINTER(GUID)])]
class IPersistStream(IPersist):
_iid_ = GUID('{00000109-0000-0000-C000-000000000046}')
_methods_ = IPersist._methods_ + [
STDMETHOD(HRESULT, 'IsDirty'),
STDMETHOD(HRESULT, 'Load', [POINTER(IStream)]),
STDMETHOD(HRESULT, 'Save', [POINTER(IStream), BOOL]),
STDMETHOD(HRESULT, 'GetSizeMax', [POINTER(ULARGE_INTEGER)])]
class IMoniker(IPersistStream):
_iid_ = GUID('{0000000F-0000-0000-C000-000000000046}')
IEnumString._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Next', [ULONG, POINTER(LPOLESTR), POINTER(ULONG)]),
STDMETHOD(HRESULT, 'Skip', [ULONG]),
STDMETHOD(HRESULT, 'Reset'),
STDMETHOD(HRESULT, 'Clone', [POINTER(POINTER(IEnumString))])]
IStream._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Seek', [LARGE_INTEGER, DWORD, POINTER(ULARGE_INTEGER)]),
STDMETHOD(HRESULT, 'SetSize', [ULARGE_INTEGER]),
STDMETHOD(HRESULT, 'CopyTo', [ULARGE_INTEGER, ULARGE_INTEGER, POINTER(ULARGE_INTEGER)]),
STDMETHOD(HRESULT, 'Commit', [DWORD]),
STDMETHOD(HRESULT, 'Revert'),
STDMETHOD(HRESULT, 'LockRegion', [ULARGE_INTEGER, ULARGE_INTEGER, DWORD]),
STDMETHOD(HRESULT, 'UnlockRegion', [ULARGE_INTEGER, ULARGE_INTEGER, DWORD]),
STDMETHOD(HRESULT, 'Stat', [POINTER(STATSTG), DWORD]),
STDMETHOD(HRESULT, 'Clone', [POINTER(POINTER(IStream))])]
IEnumMoniker._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Next', [ULONG, POINTER(POINTER(IMoniker)), POINTER(ULONG)]),
STDMETHOD(HRESULT, 'Skip', [ULONG]),
STDMETHOD(HRESULT, 'Reset'),
STDMETHOD(HRESULT, 'Clone', [POINTER(POINTER(IEnumMoniker))])]
IBindCtx._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'RegisterObjectBound', [POINTER(IUnknown)]),
STDMETHOD(HRESULT, 'RevokeObjectBound', [POINTER(IUnknown)]),
STDMETHOD(HRESULT, 'ReleaseBoundObjects'),
STDMETHOD(HRESULT, 'SetBindOptions', [POINTER(BIND_OPTS)]),
STDMETHOD(HRESULT, 'GetBindOptions', [POINTER(BIND_OPTS)]),
STDMETHOD(HRESULT, 'GetRunningObjectTable', [POINTER(POINTER(IRunningObjectTable))]),
STDMETHOD(HRESULT, 'RegisterObjectParam', [LPOLESTR, POINTER(IUnknown)]),
STDMETHOD(HRESULT, 'GetObjectParam', [LPOLESTR, POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'EnumObjectParam', [POINTER(POINTER(IEnumString))]),
STDMETHOD(HRESULT, 'RevokeObjectParam', [LPOLESTR])]
IRunningObjectTable._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Register', [DWORD, POINTER(IUnknown), POINTER(IMoniker), POINTER(DWORD)]),
STDMETHOD(HRESULT, 'Revoke', [DWORD]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetObject', [POINTER(IMoniker), POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'NoteChangeTime', [DWORD, POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'EnumRunning', [POINTER(POINTER(IEnumMoniker))])]
IMoniker._methods_ = IPersistStream._methods_ + [
STDMETHOD(HRESULT, 'BindToObject', [POINTER(IBindCtx), POINTER(IMoniker), REFIID, POINTER(c_void_p)]),
STDMETHOD(HRESULT, 'BindToStorage', [POINTER(IBindCtx), POINTER(IMoniker), REFIID, POINTER(c_void_p)]),
STDMETHOD(HRESULT, 'Reduce', [POINTER(IBindCtx), DWORD, POINTER(POINTER(IMoniker)), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'ComposeWith', [POINTER(IMoniker), BOOL, POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'Enum', [BOOL, POINTER(POINTER(IEnumMoniker))]),
STDMETHOD(HRESULT, 'IsEqual', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'Hash', [POINTER(DWORD)]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IBindCtx), POINTER(IMoniker), POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IBindCtx), POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'Inverse', [POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'CommonPrefixWith', [POINTER(IMoniker), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'RelativePathTo', [POINTER(IMoniker), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'GetDisplayName', [POINTER(IBindCtx), POINTER(IMoniker), POINTER(LPOLESTR)]),
STDMETHOD(HRESULT, 'ParseDisplayName', [POINTER(IBindCtx), POINTER(IMoniker), LPOLESTR, POINTER(ULONG), POINTER(POINTER(IMoniker))]),
STDMETHOD(HRESULT, 'IsSystemMoniker', [POINTER(DWORD)])]
S_OK = 0
RunningObjectTable = POINTER(IRunningObjectTable)()
GetRunningObjectTable = windll.ole32.GetRunningObjectTable
GetRunningObjectTable.argtypes = [DWORD, POINTER(POINTER(IRunningObjectTable))]
GetRunningObjectTable.restype = HRESULT
if GetRunningObjectTable(0, byref(RunningObjectTable)) != S_OK:
raise Exception('GetRunningObjectTable failed.')
EnumMoniker = POINTER(IEnumMoniker)()
try:
RunningObjectTable.EnumRunning(byref(EnumMoniker))
except ValueError as exception:
print(exception)
input()
我找到了 NV Access 的 NVDA(非可视化桌面访问)GitHub 存储库,其中的文件 objidl.py
包含了它们的实现,并且在一点一点地修改我的实现方式之后,我发现问题是我将 IUnknown._methods_
添加到每个接口的方法中。
所以不要像这样声明方法:
IRunningObjectTable._methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, 'Register', [DWORD, POINTER(IUnknown), POINTER(IMoniker), POINTER(DWORD)]),
STDMETHOD(HRESULT, 'Revoke', [DWORD]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetObject', [POINTER(IMoniker), POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'NoteChangeTime', [DWORD, POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'EnumRunning', [POINTER(POINTER(IEnumMoniker))])]
我应该这样声明它们:
IRunningObjectTable._methods_ = [
STDMETHOD(HRESULT, 'Register', [DWORD, POINTER(IUnknown), POINTER(IMoniker), POINTER(DWORD)]),
STDMETHOD(HRESULT, 'Revoke', [DWORD]),
STDMETHOD(HRESULT, 'IsRunning', [POINTER(IMoniker)]),
STDMETHOD(HRESULT, 'GetObject', [POINTER(IMoniker), POINTER(POINTER(IUnknown))]),
STDMETHOD(HRESULT, 'NoteChangeTime', [DWORD, POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'GetTimeOfLastChange', [POINTER(IMoniker), POINTER(FILETIME)]),
STDMETHOD(HRESULT, 'EnumRunning', [POINTER(POINTER(IEnumMoniker))])]
(我编辑了答案,因为起初我认为解决问题的方法是使用 COMMETHOD
函数而不是 STDMETHOD
函数,但现在发现情况并非如此全部)