python调用win32下的API__&&__Win32Com__[转]使用 python 写 COM

来源:互联网 发布:完美英语视听软件 编辑:程序博客网 时间:2024/04/30 21:01

http://hi.baidu.com/netspider_2007

http://hi.baidu.com/netspider_2007/blog/item/8b6ef35948d99a89810a1838.html

http://hi.baidu.com/sinomazing/blog/item/611b85160d24f710972b43e1.html

http://code.activestate.com/recipes/

http://hi.baidu.com/eeevictor/blog/item/1b57418268392699f603a6e7.html

python调用vc中的API
准备工作: 安装pywin32-210.5.win32-py2.5.exe

例1:最简单的MessageBox函数
import win32api, win32gui 
import win32con, winerror,win32event,pywintypes
import sys, os,time
win32api.MessageBox(0,'hello', 'WYM',win32con.MB_OK)

例2:进程监控
#Mutex.py
mutex=None
mutex=win32event.CreateMutex(None,pywintypes.FALSE,"MutexWym")
if(win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS):
    print"Opened existing mutex object", mutex
else:
    print "Created new mutex" 
time.sleep(10)
win32api.CloseHandle(mutex)
print "close Mutex"
time.sleep(10)

#MonitorProcess.py

import win32api, win32gui 
import win32con, winerror,win32event ,pywintypes
import sys, os,time

STANDARD_RIGHTS_REQUIRED = 0x000F0000L
SYNCHRONIZE = 0x00100000L
MUTANT_QUERY_STATE = 0x0001
MUTEX_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | MUTANT_QUERY_STATE
try:
    while 1:
        time.sleep(2)
        hMutex=win32event.OpenMutex(MUTEX_ALL_ACCESS,pywintypes.FALSE,"MutexWym")
        print win32api.GetLastError()        
        if hMutex is not None:
            print "Mutex open"
            win32api.CloseHandle(hMutex)
        else:
            print "Mutex not open"
            break
except pywintypes.error, (errno, object, strerror):
    print "Error in", object, ":", strerror

如何使用kernel32的API呢
例3:
import pywintypes
import winerror, win32con
import win32api, win32event, win32file, win32pipe, win32process, win32security
import win32service, win32serviceutil, servicemanager,ntsecuritycon
from ctypes import *   #本例包括这个头文件

hMutex = windll.kernel32.CreateMutexA(None, 0, "szMutex")
#其它API同理,比如像windll.kernel32.InitializeCriticalSection() 等等 


a、python中涉及的windows下的类型?
通过pywintypes 可以获得这个数据类型 
b、获得窗口句柄
通过FindWindow这API来查找相应的窗口的句柄,然后发消息给这个窗口,就可以实现这个功能
ct = win32api.GetConsoleTitle()   
hd = win32gui.FindWindow(0,ct)  
 
win32gui.ShowWindow(hd,
0)

----------------------------------------------------------------------------

注意缩进!

转 用Python实现COM对象 能在VB等开发语言中调用 从而实现系统和Python扩展的独立开发 无缝集成
2009年04月07日 星期二 下午 03:37

作者:马维峰 李林 王晓蕊



 1.2.1 Python的集成方式

在一般的编程语言中,集成或调用Python有以下几种方式:(1)在C或C++语言中,可以利用Python提供的接口,调用Python的特定功 能(Rossum,2003);(2)通过数据文件方式,通过操作系统的管道方式,直接调用Python执行环境和功能模块完成特定功能;(3)在 Windows环境下,可以使用PythonCOM扩展模块将Python编写的对象包装成COM对象,供支持COM的编程语言调用 (Hammond,2000)。其中(1)和(3)种方法为“无缝”集成,方法(2)为松散集成。

本文将通过PythonCOM扩展模块来完成与SuperMap Object相互调用。PythonCOM是由ActiveState公司开发的一个Python与COM、ASP集成的扩展模块,有关PythonCOM的信息请参考ActiveState公司网站(http://www.activestate.com)。以下将详细介绍如何创建一个可以被其他编程语言调用的Python模块,以及此模块如何与SuperMap Object交互完成特定的任务。

1.2.2 应用Python实现COM对象

使用Python实现一个COM对象首先需要定义一个Python类,实现需要的属性和方法;其次需要应用PythonCOM扩展,实现 ProgID、CLSID等属性,在注册表里注册这个Python类,使其成为一个可以被调用的COM对象。下面将通过一个简单的例子来说明这个过程。
我们来设计一个可以计算用户表达式的COM对象,以下是代码:

 # SimpleEVAL.py – 表达式求解
class PythonEVAL:
_public_methods_ = [ 'MyEval' ]
_reg_progid_ = "PythonGISDemos.EVAL"
# Guid of this COM Searver
_reg_clsid_ = "{6288B5B7-870F-494E-A4F0-99868729804E}"

def MyEval(self, source, my_x):
x = my_x
return eval(source)
# 自注册部分
if __name__=='__main__':
print "Registering COM server..."
import win32com.server.register
win32com.server.register.UseCommandLine(PythonEVAL)

  以上的文件定义有3个特殊的属性字段,分别是:

_public_methods_ 

可以被调用的方法列表,本代码只有一个方法“MyEval”。

_reg_progid_ 

对象的名称,用来调用这个对象时使用。

_reg_clsid_ 

COM对象的CLSID,可以使用“pythoncom.CreateGuid()”这个方法来生成,也可以使用别的工具。

source----含x的表达式,如下图中3*x-x*x,my_x 为x的具体值.

如下图函数return的就是3*x-x*x=3*2-2*2=4




图上为错误的参数--unregister应该为两个-
MyEval为我们定义的方法,参数为一个含“x”的表达式(字符串),和x的具体值,然后调用这个方法,返回计算后的值。后面的部分为自注册模块, 如果是在Python的交互环境下直接调用此模块,则运行这段代码。将这个文件保存在“Python23\Lib\site-packages”这个目录 下,首先运行一次,使其在注册表里注册这个COM组件。

这个对象可以应用在某些需要用户给出具体的表达式进行分析计算的模块中。在编写这个类的过程中,可以在Python的交互环境下边编写边测试,有助于验证算法和逻辑的正确性,保证开发效率和质量。

Python开发的COM对象也可以通过命令行进行注册和反注册。注册一个对象:“Python.exe YourServer.py”;反注册一个对象:“Python.exe YourServer.py --unregister”。需要说明的是这个对象一定要有以上程序的注册部分这一段代码。

PythonCOM还定义了除了“_public_methods_”以外其他一些特殊的属性字段,可以描述COM对象的其他特性。在代码中,还可以 通过“raise COMException("the error info")”这样的语句来进行错误处理。对于使用Python创建COM对象的其他细节问题请参考PythonCOM相关文档。

1.2.3 调用Python实现的COM对象

调用Python编写的COM对象和调用其他COM对象方法一样,以下将通过VB代码来实例说明其调用方法。

在VB中新建一个工程,在缺省窗体上放置3个文本框和一个按钮,在Form_Load事件里编写对COM对象的初始化代码,在按钮点击事件里,编写COM对象调用的代码,在Form_Unload事件里,销毁这个对象。全部代码如下:

 Public myServer As Object
Private Sub Command1_Click()
Text3.Text=myServer.MyEval(Text1.Text,Int(Text2.Text))
End Sub
Private Sub Form_Load()
Set myServer = CreateObject("PythonGISDemos.EVAL")
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set myServer = Nothing
End Sub


整个代码和调用其他COM对象没有什么差别。以下是程序运行的界面,对x=2,表达式为“3*x – x*x”进行求解,结果是2。 

 

图 1 VB中调用Python编写的COM对象的运行结果

我们可以把这段代码插入使用SuperMap Object等组件式GIS,开发语言为VB或其他语言的开发项目中需要用户给出具体的表达式进行分析计算的模块中。需要说明的是,对于参数传递,数据类 型,对象调用等使用COM开发需要注意的问题,在这里一样需要注意。另外有两个问题需要注意,第一,对于VB开发环境,VB是大小写不敏感的,而 Python是区分大小写的;第二是Unicode的问题,COM传递的字符串都是Unicode,在Python中处理使用之前要根据需要转换为Python的字符串。

 1.3 应用实例

下面将使用Python来实现一个最小二乘拟合的模块。以下是代码:

 # LeastSq.py – 最小二乘拟合
from scipy import *
from scipy.optimize import leastsq

 class PythonSq:
_public_methods_ = ['AddX','AddY','leastsq','GetP']
_reg_progid_ = "PythonGISDemos.LeastSq"
# Guid of this COM Searver
_reg_clsid_ = "{6278B5B7-870F-494E-A4F0-92368724804E}"
#程序中需要拟合的X和Y的值
x=[]
y=[]
#输入X和Y的值,由于一般语言没有对应的序列等数据结构,所以逐个输入
def AddX(self, xx):
self.x.append(xx)
def AddY(self, yy):
self.y.append(yy)
#求解剩余变量
def residuals(self, p, y, x):
a, b, c = p
y = array(y) #将序列转换为矩阵
x = array(x)
err = y - (a*x*x + b*x + c)
return err
#求解参数
def leastsq(self):
m_p = [1.0,1.0,1.0]
self.p = leastsq(self.residuals,m_p,args=(self.y,self.x))
#求返回值
def GetP(self, index):
return self.p[0][index]
# 自注册部分(略)


程序代码的说明见注释。程序使用了SciPy扩展模块optimize模块(对于非线性方程,进行回归分析建议使用本方法,SciPy另外专门有线性代数模块(构建于ATLAS LAPACK和BLAS),可以进行线性代数运算,对于线性回归,具有更好的速度和稳定性。) (http://www.scipy.org),代码量很短,核心代码仅10余行,主要处理了输入和输出,定义了剩余变量的求解方式,主要的最小二次拟合 的代码仅1行,直接调用了optimize模块的leastsq方法。如果要改变拟合方程式,只需在residuals方法内修改“err = y - (a*x*x + b*x + c)”括号内的部分即可。数据通过逐个输入方式输入,然后由Python读进其List中(如果需要传递大数据量的数据,笔者建议使用外部文件方式,由 VB等客户程序创建一个数据文件,然后将此文件路径传递给Python的COM组件,由Python读入(Python具有非常简单的文件读取和写入方式),构建为内部的List、Array或Matrix。) 。

在VB或其他语言中新建一个工程,测试此COM对象,以下为VB6下一个简单的测试代码:

 Dim objSq As Object
Set objSq = CreateObject("PythonGISDemos.LeastSq")
Dim i As Integer
'初始化回归值
For i = 0 To 100
objSq.AddX (CSng(i))
objSq.AddY (CSng(i) ^ 2 + Rnd())
Next
'调用回归方法
objSq.leastsq
MsgBox "A = " & objSq.GetP(0) 
MsgBox "B = " & objSq.GetP(1) 
MsgBox "C = " & objSq.GetP(2) 
Set objSq = Nothing


对于非线性方程,需要给出参数的初始值(leastsq方法内的m_p的值)。我们也可以使用前面举例介绍过的“eval”函数,编写一个可以对任意 表达式进行求解的最小二次拟合模块。对于代码的编写,可以首先在Python的交互式开发环境和IDE(Python自带的IDLE,PythonWin 等)下,边编写边测试,确定语法和逻辑没有错误后,即可完成模块,然后在其他环境下测试和使用,可以提高开发效率和质量。

----------------------------

from : http://www.cppblog.com/bigsml/archive/2008/08/14/58851.html

Python 支持Com调用(client com) 以及撰写COM 组件(server com). 
1. com 调用示例(使用Windows Media Player 播放音乐)

from win32com.client import Dispatch
mp 
= Dispatch("WMPlayer.OCX")
tune 
= mp.newMedia("C:/WINDOWS/system32/oobe/images/title.wma")
mp.currentPlaylist.appendItem(tune)
mp.controls.play()


2. com server 的编写
主要可以参考 <<Python Programming on Win32 之 Chapter 12 Advanced Python and COM http://oreilly.com/catalog/pythonwin32/chapter/ch12.html >>
示例(分割字符串) 
- 代码

class PythonUtilities:
     _public_methods_ 
= [ 'SplitString' ]
     _reg_progid_ 
= "PythonDemos.Utilities"
    
# NEVER copy the following ID 
    # Use "print pythoncom.CreateGuid()" to make a new one.
     _reg_clsid_ = "{41E24E95-D45A-11D2-852C-204C4F4F5020}"
    
    
def SplitString(self, val, item=None):
        
import string
        
if item != None: item = str(item)
        
return string.split(str(val), item)

# Add code so that when this script is run by
#
 Python.exe, it self-registers.
if __name__=='__main__':
    
print "Registering COM server"
    
import win32com.server.register
     win32com.server.register.UseCommandLine(PythonUtilities)


- 注册/注销Com 

Command-Line Option

Description

The default is to register the COM objects.

--unregister

Unregisters the objects. This removes all references to the objects from the Windows registry.

--debug

Registers the COM servers in debug mode. We discuss debugging COM servers later in this chapter.

--quiet

Register (or unregister) the object quietly (i.e., don't report success).


- 使用COM 
可以在python 命令行下运行

>>> import win32com.client
>>> s = win32com.client.Dispatch("PythonDemos.Utilities")
>>> s.SplitString("a,b,c"",")
((u
'a', u'a,b,c'),)
>>>


3. python server com 原理 
其实在注册表中查找到python com 的实现内幕

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}]
@
="PythonDemos.Utilities"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Debugging]
@
="0"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories]

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories\{B3EF80D0-68E2-11D0-A689-00C04FD658FF}]

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\InprocServer32]
@
="pythoncom25.dll"
"ThreadingModel"="both"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\LocalServer32]
@
="D:\\usr\\Python\\pythonw.exe \"D:\\usr\\Python\\lib\\site-packages\\win32com\\server\\localserver.py\" {41E24E95-D45A-11D2-852C-204C4F4F5020}"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\ProgID]
@
="PythonDemos.Utilities"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOM]
@
="PythonDemos.PythonUtilities"

[HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOMPath]
@
="D:\\"

inproc server 是通过pythoncom25.dll 实现
local server 通过localserver.py 实现
com 对应的python 源文件信息在 PythonCOMPath & PythonCOM

http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx

主要的资料是《Python Programming On Win32》,这本书的作者之一Mark Hammond就是win32com的开发者,也是PythonWin的开发者,因此很有权威。经过几天的学习已经大致明白了,以前对于Com的难以理解的东西,在经过Python封装后已经变得很简单了。

后来又发现一个收集有关Python 在Windows下编程的网站,发现有一些Com编程的资源,大家有兴趣可以看一看如何在 Python 下调用Windows的应用程序。

下面是一段可以使用 Windows Media Player 来播放音乐的代码,大家可以马上在交互环境下试验,当然前提是你需要安装 PythonWin32 包,现在最新的是204版。

代码如下:

>>> from win32com.client import Dispatch
>>> mp = Dispatch("WMPlayer.OCX")
>>> tune = mp.newMedia("C:/WINDOWS/system32/oobe/images/title.wma")
>>> mp.currentPlaylist.appendItem(tune)
>>> mp.controls.play()

很简单吧。如果想停止可以执行:

>>> mp.controls.stop()

Python 的 Com 编程主要包括两个方面:客户端和服务器。

客户端是用来调用其它的 Com 对象,因此从上面第一行可以看到client,就知道这是客户端编程。如果要编服务器的程序则需要从win32com.server来导入了。Dispatch是用来获得 Com 对象的方法。为什么叫Dispatch呢?因为在 Com 有一个接口叫 IDispatch ,它是一个高层接口,主要可以实现方法和属性的动态获取。也就是说,当你得到一个Com对象后你并不知道它的方法和属性都有些什么,而是动态获取的。所有实现IDispatch的对象需要实现两个方法:GetIDsOfNames()和Invoke()。GetIDsOfNames用来查找一个方法或属性是否存在,如果存在则返回它的一个数字索引,然后要使用这个索引传入Invoke来进行调用。从上面的代码你看不到这样的处理,因为 Python 自动给你完成了。所以使用 Python 写 Com 的程序真是方便啊。因此后面对于对象的操作都是自动进行GetIDsOfNames()和Invoke()进行调用了。这在Com中可以称之为后联编,也就是后期绑下。同时 Python 也支持前联编也就是前期绑定。如果想使用这种方法,需要执行MakePy.py这个程序。它会让你选择要处理的COM对象,然后生成一个python程序,用来处理前期绑定。前期绑定则不再需要动态获取了,因此它可以提高运行速度,同时还可以处理常量,而在后期绑定是处理不了的。这些细节在上面的书中都有讲述。

原创粉丝点击