Python 使用ADO和Win32 COM获取SQL Server消息

Python 使用ADO和Win32 COM获取SQL Server消息,python,sql-server,ado,win32com,adodbapi,Python,Sql Server,Ado,Win32com,Adodbapi,我目前正在尝试编写一个工具,使不懂计算机的用户能够非常轻松地备份SQL Server数据库 为此,我希望使用ADO、Win32 COM和adodbapi的有趣组合。目前,我可以轻松连接到服务器并发出BACKUP DATABASET-SQL命令 这是可行的,但是执行命令通常需要很长时间(特别是在非常大的数据库上)。为此,我希望捕获并解析InfoMessageevent(),并使用它来显示百分比条/计数器 我也做到了这一点,现在我被困在最后一个障碍,解析事件。文档说应该在pError参数中向我传递o

我目前正在尝试编写一个工具,使不懂计算机的用户能够非常轻松地备份SQL Server数据库

为此,我希望使用ADO、Win32 COM和adodbapi的有趣组合。目前,我可以轻松连接到服务器并发出
BACKUP DATABASE
T-SQL命令

这是可行的,但是执行命令通常需要很长时间(特别是在非常大的数据库上)。为此,我希望捕获并解析
InfoMessage
event(),并使用它来显示百分比条/计数器

我也做到了这一点,现在我被困在最后一个障碍,解析事件。文档说应该在
pError
参数中向我传递or对象。然而,win32com向我传递了一个我不知道如何处理的
PyIUnknown
对象

以下是我迄今为止编写的代码:

import win32com
import pythoncom
import adodbapi
from win32com.client import gencache
gencache.EnsureModule('{2A75196C-D9EB-4129-B803-931327F72D5C}', 0, 2, 8)

defaultNamedOptArg=pythoncom.Empty
defaultNamedNotOptArg=pythoncom.Empty
defaultUnnamedArg=pythoncom.Empty

class events():
    def OnInfoMessage(self, pError, adStatus, pConnection):
        print 'A', pError
        #print 'B', adStatus
        #print 'C', pConnection

# This is taken from the makepy file
#    def OnCommitTransComplete(self, pError=defaultNamedNotOptArg, adStatus=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg): pass
    def OnWillExecute(self, Source=defaultNamedNotOptArg, CursorType=defaultNamedNotOptArg, LockType=defaultNamedNotOptArg, Options=defaultNamedNotOptArg
            , adStatus=defaultNamedNotOptArg, pCommand=defaultNamedNotOptArg, pRecordset=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg):
        return Source
#    def OnDisconnect(self, adStatus=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg): pass
    def OnExecuteComplete(self, RecordsAffected=defaultNamedNotOptArg, pError=defaultNamedNotOptArg, adStatus=defaultNamedNotOptArg, pCommand=defaultNamedNotOptArg
            , pRecordset=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg): pass
        #print pError
    def OnWillConnect(self, ConnectionString=defaultNamedNotOptArg, UserID=defaultNamedNotOptArg, Password=defaultNamedNotOptArg, Options=defaultNamedNotOptArg
            , adStatus=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg): pass
#    def OnConnectComplete(self, pError=defaultNamedNotOptArg, adStatus=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg): pass
#    def OnBeginTransComplete(self, TransactionLevel=defaultNamedNotOptArg, pError=defaultNamedNotOptArg, adStatus=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg):pass
#    def OnRollbackTransComplete(self, pError=defaultNamedNotOptArg, adStatus=defaultNamedNotOptArg, pConnection=defaultNamedNotOptArg): pass




if __name__ == '__main__':

    pythoncom.CoInitialize()
    conn = win32com.client.DispatchWithEvents("ADODB.Connection", events)
    print dir(conn)
    conn.ConnectionString = 'Initial Catalog=test; Data Source=HPDX2250RAAZ\\SQLEXPRESS; Provider=SQLOLEDB.1; Integrated Security=SSPI'
    conn.CommandTimeout = 30
    print conn.ConnectionString
    conn.Open()

    con = adodbapi.Connection(conn)

    c = con.cursor()
    import time
    print 'Execute'
    time.sleep(1)
    c.execute(u"BACKUP DATABASE [test] TO DISK = N'c:/test/test2' WITH STATS = 1")
    print 'Done Execute'
任何人都可以从事件中提取信息性消息吗

这就是它在(我认为)中的实现

有关其中一条消息的示例,请启动SQL Server Management Studio并使用脚本运行备份(您可以使用备份对话框和左上角的脚本按钮生成脚本)。您会注意到,当您运行脚本时,消息框将填充完成百分比消息。这就是我想要的

编辑: 下面是我用来询问传递给
InfoMessage
的COM对象的新代码。这是基于下面的答案,我把它放在这里,以防其他人需要它

def OnInfoMessage(self, pError, adStatus, pConnection):
    print 'Info Message'
    a = pError.QueryInterface(pythoncom.IID_IDispatch)
    a = win32com.client.Dispatch(a)
    print a.Description
    print a.Number
    print a.Source
    #print 'B', adStatus
    c = pConnection.QueryInterface(pythoncom.IID_IDispatch)
    c = win32com.client.Dispatch(c)
    print c.Errors.Count
    print c.Errors.Item(0).Description
    print c.Errors.Clear()
    print 'c', adStatus

读取MSDN时,似乎只有
Error
对象应该传递给事件处理程序。如果存在多个错误,可以从
连接
对象的
错误
集合中获取这些错误。因此,您应该只希望将错误对象传递到
InfoMessage()
。如果您改为使用PyIUnknown,也许您可以尝试对其调用
QueryInterface()
,并请求IDispatch?您也可以尝试请求特定的自定义接口
Error
uses,但我不记得Pythoncom是否支持自定义(即非IDispatch)接口,而且我的internet正在爬行,因此我无法检查,因此您必须自己检查。不管怎样,IDispatch都应该工作,因为VB6就是这样使用的。

请求
IDispatch
接口,然后将其传递给
win32com.client.Dispatch()
会生成一个后期绑定的COM对象,允许我访问所需的数据。但是,我只收到一个带有错误对象的
InfoMessage
调用。正如文档所述,如果有多个错误,您可以从
连接中获取所有错误。错误
。但我不确定这将如何帮助您跟踪进度。我已经查看了访问
InfoMessage
连接
对象,以及我调用后的原始对象。这两个对象只包含一个
错误
,它是在
peror
参数中传递给
InfoMessage
的对象。每个完成百分比消息都应该有一个
错误
。使用
STAT=10
时,应该有~10
错误
s以及
备份
命令发送的一些其他消息。