处理 python COM中的枚举对象

本文介绍如何在Python中处理COM枚举对象,通过ctypes库定义C语言结构并实现与C语言布局一致的数据结构。同时利用python win32扩展的win32com.server.util集合对象,方便在VBScript中使用For Each...Next结构。文中提供了具体代码示例,包括myStructure、CollectionGateway、comPoint和comPointList等类,展示了如何创建和操作这些COM对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

在工作中需要做测试,开发是用了python,一来语法简单,而来也有robotframework可以配合使用。开发一般用QTP测试比较少,QTP测试也比较慢。所以可以直接使用python开发的库,或者最多提炼一些关键词,用robotframework来做测试也好。

测试方面也针对同样的测试项做了开发,由于终端传递出来的是c数据结构,比较复杂,而用dll调用的方式由于没有跟c很好的接口,导致提取结构非常辛苦,后来想了个办法,用micString+micByRef预先分配好字符串,然后dll库内把数据用sprintf格式化出name=value;这种格式来使用。然后在vbs中再恢复出来,非常辛苦。当然,这些值也可以从页面取到,不过QTP操作页面有时候速度比较慢,没有直接从接口取数据快。

 

针对这种情况,用python+python win32扩展把python对象封装出来供使用。里面使用了ctypes库,以便于定义c语言的结构,能做到跟c语言布局一样。而且可以定义复杂的数据结构。也很容易在ctypes对象和string之间做pack和unpack。另外,使用了python win32扩展中的win32com.server.util的集合对象,以便于在vbs中使用for each...next结构。 废话不多说了。下面贴出代码

 


 

 

 

import string

import pythoncom

import pywintypes

import winerror

import types

from ctypes import *

from win32com.server import policy

from win32com.server.util import NewEnum,NewCollection,wrap,unwrap,Collection,ListEnumeratorGateway

from win32com.server.exception import COMException

 

class myStructure(Structure):

    def __str__(self):      

        s=[]

        for k,v in self._fields_:

            if type(v)==type(c_int) or type(v)==type(Structure): #SimpleType

                s.append("%s=%s"%(k,getattr(self,k)))

            elif type(v)==type(Array):

                s.append('%s=%s'%(k,'['+','.join(["%s" % getattr(self,k)[i] for i in range(v._length_)])+']'))

            else:

                pass

        return '%s(%s)'%(self.__class__.__name__,','.join([i for i in s]))

 

class CollectionGateway(Collection):

  "A collection which wraps a sequence's items in gateways"

  def Item(self, *args):

    if len(args) != 1:

      raise COMException(scode=winerror.DISP_E_BADPARAMCOUNT)

 

    try:

      return wrap(self.data[args[0]])

    except IndexError, desc:

      raise COMException(scode=winerror.DISP_E_BADINDEX, desc=str(desc))  

 

  def _NewEnum(self):

    return NewEnum(self.data,ListEnumeratorGateway)  

 

class comPoint(myStructure):

    _fields_=[('x',c_int),('y',c_int)]

    _public_methods_=[]

    _public_attrs_=['x','y']

 

class comPointList(myStructure,CollectionGateway):

    _fields_=[('num',c_int),('list',comPoint * 2)]  

    _reg_progid_ = "Pt.Point"

    _reg_clsid_ = "{CB2E1BC5-D6A5-11D2-852D-204C4F4F5024}"

    _public_methods_=['CStr']

    _public_attrs_=['num']

 

    def CStr(self):

        return str(self)

 

    def Item(self, *args):

        if len(args) != 1:

          raise COMException(scode=winerror.DISP_E_BADPARAMCOUNT)

 

        try:

          return wrap(self.list[args[0]])

        except IndexError, desc:

          raise COMException(scode=winerror.DISP_E_BADINDEX, desc=str(desc))  

 

    def _NewEnum(self):

        return NewEnum(self.list,ListEnumeratorGateway)  

 

if __name__=='__main__':

    import win32com.server.register

    win32com.server.register.UseCommandLine(comPointList)

 


这里面核心部分是引入了CollectionGateway,这样对每个集合对象在传出的时候都会wrap成com对象。_NewEnum则在For Each的时候被自动调用,当然,也暴露了一个num属性,用于知道有几个元素,另外,用Item也可以直接取对应元素。

 

下面是测试的vbs代码

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值