Python,win32 COM:我有一个类名,但无法创建客户端,“'不支持这样的接口'

2024-09-28 18:55:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Win32 COM接口的新手。我的最终目标是连接到OPC服务器。我在这个过程的早期就被卡住了。有一个Win32 COM服务枚举我机器上所有可用的OPC服务器(OPCEnum.exe服务),但我无法从程序访问它。我的计算机上的商业OPC工具可以执行此任务,因此我知道OPC服务器枚举器已安装并正在运行。我可以在Windows系统服务中看到它

我的系统配置是:Windows7 64位,Anaconda中的Python3.7 64位,使用pip安装的pywin32(所以它也应该是64位,尽管我还没有弄清楚如何检查它)

下面是最简单的示例代码:

import win32com.client as w32

def com_client_verbose(client_class_name):
    title = client_class_name + " client"
    print(title)
    print("=" * len(title))
    com_client = w32.gencache.EnsureDispatch(client_class_name)
    print(type(com_client))
    print(dir(com_client))
    print("\n\n")
    return com_client

def class_name_verbose(clsid):
    title = clsid + " module"
    print(title)
    print("=" * len(title))
    module = w32.gencache.EnsureModule(clsid, 0, 1, 0)
    print(type(module))
    path = module.__file__
    print(path)
    # INSPECT the CODE to obtain the class name. Is this really necessary?
    # https://stackoverflow.com/questions/17225798/python-win32com-dont-know-name-of-module
    with open(path, "r") as f:
        for line in f.readlines():
            if line.startswith("# This CoClass is known by the name"):
                print(line, "\n\n")
                return line.split("'")[1]
        else:
            raise RuntimeError("CoClass comment line not found.")

# Most Windows machines have Excel installed. Excel exposes a COM interface.
print("\n\n")
xl_client = com_client_verbose("Excel.Application")

# OPCEnum CLSID is documented at: http://www.opcti.com/dcom-error-for-clsid.aspx
# win32com.client.combrowse confirms that this CLSID is active on my system.
opc_enum_clsid = "{13486D43-4821-11D2-A494-3CB306C10000}"
opc_enum_class_name = class_name_verbose(opc_enum_clsid)

# Now that we have a class name for OPCEnum, try to create its COM client.
# This fails.
opc_enum_client = com_client_verbose(opc_enum_class_name)

这是输出。直到最后一行看起来还不错

Excel.Application client
========================
<class 'win32com.gen_py.00020813-0000-0000-C000-000000000046x0x1x9._Application.
_Application'>
['ActivateMicrosoftApp', 'AddChartAutoFormat', 'AddCustomList', 'CLSID', 'Calcul
ate', 'CalculateFull', 'CalculateFullRebuild', 'CalculateUntilAsyncQueriesDone',
 'CentimetersToPoints', 'CheckAbort', 'CheckSpelling', 'ConvertFormula', 'DDEExe
cute', 'DDEInitiate', 'DDEPoke', 'DDERequest', 'DDETerminate', 'DeleteChartAutoF
ormat', 'DeleteCustomList', 'DisplayXMLSourcePane', 'DoubleClick', 'Dummy1', 'Du
mmy10', 'Dummy11', 'Dummy12', 'Dummy13', 'Dummy14', 'Dummy2', 'Dummy20', 'Dummy3
', 'Dummy4', 'Dummy5', 'Dummy6', 'Dummy7', 'Dummy8', 'Dummy9', 'Evaluate', 'Exec
uteExcel4Macro', 'FileDialog', 'FindFile', 'GetCaller', 'GetClipboardFormats', '
GetCustomListContents', 'GetCustomListNum', 'GetFileConverters', 'GetInternation
al', 'GetOpenFilename', 'GetPhonetic', 'GetPreviousSelections', 'GetRegisteredFu
nctions', 'GetSaveAsFilename', 'Goto', 'Help', 'InchesToPoints', 'InputBox', 'In
tersect', 'MacroOptions', 'MailLogoff', 'MailLogon', 'NextLetter', 'OnKey', 'OnR
epeat', 'OnTime', 'OnUndo', 'Quit', 'Range', 'RecordMacro', 'RegisterXLL', 'Repe
at', 'ResetTipWizard', 'Run', 'Save', 'SaveWorkspace', 'SendKeys', 'SetDefaultCh
art', 'SharePointVersion', 'ShortcutMenus', 'Support', 'Undo', 'Union', 'Volatil
e', 'Wait', '_ApplyTypes_', '_Evaluate', '_FindFile', '_MacroOptions', '_Run2',
'_WSFunction', '_Wait', '__call__', '__class__', '__delattr__', '__dict__', '__d
ir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribu
te__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__iter
__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__red
uce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__
', '__weakref__', '_get_good_object_', '_get_good_single_object_', '_oleobj_', '
_prop_map_get_', '_prop_map_put_', 'coclass_clsid']



{13486D43-4821-11D2-A494-3CB306C10000} module
=============================================
<class 'module'>
C:\Users\FOO\AppData\Local\Temp\gen_py\3.7\13486D43-4821-11D2-A494-3CB306
C10000x0x1x1.py
# This CoClass is known by the name 'OPC.ServerList.1'



OPC.ServerList.1 client
=======================
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\dynamic.py",
line 89, in _GetGoodDispatch
    IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221021, 'Operation unavailable', None, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\runpy.py", line 183, in _run_module_as_main
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
  File "C:\ProgramData\Anaconda3\lib\runpy.py", line 109, in _get_module_details
    __import__(pkg_name)
  File "C:\Users\foo\Documents\OPC\win32com minimal example.py", line 49, in <module>
    opc_enum_client = com_client_verbose(opc_enum_class_name)
  File "C:\Users\foo\Documents\OPC\win32com minimal example.py", line 14, in com_client_verbose
    com_client = w32.gencache.EnsureDispatch(client_class_name)
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\gencache.py", line 527, in EnsureDispatch
    disp = win32com.client.Dispatch(prog_id)
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\dynamic.py", line 114, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\dynamic.py", line 91, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147467262, 'No such interface supported', None, None)

第一步,我的积极控制:如果我知道一个COM类名,比如“Excel.Application”,我可以将一个live code对象返回到它的COM接口

步骤2:如果我知道CLSID,但不知道COM类名,我可以检索该名称。我不喜欢这样做——通过检查Python脚本本身,寻找注释行——但这是this StackOverflow comment中建议的方法,它似乎可以工作

步骤3失败。尽管我从CLSID中获得了COM类名“OPC.ServerList.1”,但Windows/pywin32告诉我没有与该名称关联的接口

我还尝试了不带“.1”的类名“OPC.ServerList”,认为“.1”可能是某种实例号。这也失败了

任何建议都将不胜感激,谢谢


Tags: nameinpycomclientverboselineclass
1条回答
网友
1楼 · 发布于 2024-09-28 18:55:26

COM有两(三)种接口:自定义接口(其中的方法签名和类型实际上可以是您喜欢的任何类型),自动化接口(必须源自IDispatch,并且方法的外观和类型选择有限)。还有接口(满足上述两种类型限制的接口)

OPCEnum中的所有接口以及OPC经典服务器的所有接口都是自定义接口

我不是python专家,但我相信win32com只支持自动化接口。 因此,不能将Win32 COM与OPCEnum或OPC Classic服务器一起使用

我在谷歌上搜索了一下,发现了这个:https://www.codeproject.com/Articles/22563/Working-with-custom-COM-interfaces-from-Python。我不确定它是否有效,但它肯定包含了可以推动你前进的有趣信息。(tl;dr:建议使用“comtypes”而不是“pythoncom”)

相关问题 更多 >