处理 python COM中的枚举对象

来源:互联网 发布:网络暴力的事件 编辑:程序博客网 时间:2024/06/05 17:55

 

在工作中需要做测试,开发是用了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代码

 

 

 

 

原创粉丝点击