使用ADO和win32com获取SQL Server消息

1 投票
1 回答
1942 浏览
提问于 2025-04-16 16:55

我现在正在尝试写一个工具,让不懂电脑的用户也能轻松备份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

1 个回答

0

根据MSDN的说明,只有Error对象应该被传递给事件处理程序。如果有多个错误,你可以从你的Connection对象的Errors集合中获取它们。所以,你应该只期待InfoMessage()接收到Error对象。如果你收到的是PyIUnknown,那你可以尝试在它上面调用QueryInterface(),请求IDispatch?你也可以尝试请求Error使用的特定自定义接口,但我不记得Pythoncom是否支持自定义(也就是非)接口,而且我的网络现在很慢,所以我不能查证,你得自己去确认。无论如何,IDispatch应该都能工作,因为这是VB6使用的。

撰写回答