【问题标题】:Getting SQL Server messages using ADO and win32com使用 ADO 和 win32com 获取 SQL Server 消息
【发布时间】:2011-05-04 21:26:48
【问题描述】:

我目前正在尝试编写一个工具,它可以让不懂计算机的用户轻松备份 SQL Server 数据库。

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

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

这我也成功了,我现在被困在最后一个障碍,解析事件。 MSDN 文档说我应该在 pError 参数中传递一个 ErrorErrors 对象。但是 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'

任何人都可以从事件中提取信息消息吗?

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

对于这些消息之一的示例,启动 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

【问题讨论】:

    标签: python sql-server ado win32com adodbapi


    【解决方案1】:

    阅读 MSDN,似乎只有 Error 对象应该被传递给事件处理程序。如果有多个错误,您可以从您的Connection 对象的Errors 集合中获取它们。所以你应该只期望错误对象被传递给InfoMessage()。如果你得到 PyIUnknown,也许你可以尝试调用 QueryInterface() 并请求 IDispatch?您也可以尝试请求 Error 使用的特定自定义接口,但我不记得 Pythoncom 是否支持自定义(即非 IDispatch)接口,而且我的互联网现在正在爬行,所以我无法检查所以你会必须自己检查。无论如何,IDispatch 无论如何都应该工作,因为这就是 VB6 使用的。

    【讨论】:

    • 请求IDispatch 接口,然后将其传递给win32com.client.Dispatch() 会生成一个后期绑定的COM 对象,让我可以访问我需要的数据。但是,我只接到一个带有错误对象的InfoMessage 电话。
    • 如文档所述,如果有多个错误,您可以从Connection.Errors 获取所有错误。不过,我不确定这将如何帮助您跟踪进度。
    • 我查看了到达InfoMessageConnection 对象以及我拨打电话后的原始对象。这两个对象都只包含一个Error,它是在pError 参数中传递给InfoMessage 的那个。
    • 每个完成百分比的消息都应该有一个Error。对于STAT = 10,应该有~10 个Errors 以及BACKUP 命令发送的一些其他消息。
    猜你喜欢
    • 2014-12-27
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多