В настоящее время я пытаюсь написать инструмент, который упростит для неграмотного грамотного пользователя резервное копирование базы данных SQL Server.
Для этого я надеюсь использовать интересное сочетание ADO, win32com и adodbapi. В настоящее время я могу легко подключиться к серверу и выдает команду BACKUP DATABASE
T-SQL.
Это работает, однако для выполнения команды часто требуется много времени (особенно в очень больших базах данных). С этой целью я надеялся захватить и проанализировать событие InfoMessage
(MSDN) и использовать его для отображения процентного бара/счетчика.
Это я тоже справился, теперь я застрял в последнем препятствии, разобрав событие. MSDN docs говорят, что мне нужно передать либо Error или Ошибки в параметре pError
. Однако 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 и запустите резервную копию с помощью script (вы можете сгенерировать script с помощью диалога резервного копирования и кнопки script в верхнем левом углу). Вы заметите, что при запуске script в поле сообщений будут заполняться процентные сообщения. Это то, что я хочу.
Ниже приведен новый код, который я использую для опроса COM-объектов, которые передаются в InfoMessage
. Это основано на ответе ниже, я помещаю его здесь, если кому-то это понадобится.
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
должны передаваться обработчикам событий. Если имеется несколько ошибок, вы можете получить их из коллекции Errors
вашего объекта Connection
. Поэтому вы должны ожидать, что объекты Error будут переданы в InfoMessage()
. Если вместо этого вы получите PyIUnknown, возможно, вы попытаетесь позвонить на него QueryInterface()
и запросить IDispatch? Вы также можете попробовать запросить использование специального пользовательского интерфейса Error
, но я не помню, поддерживает ли Pythoncom пользовательские (то есть не IDispatch) интерфейсы, и мой интернет сканирует прямо сейчас, поэтому я не могу проверить, чтобы вы должны убедиться в этом сами. Во всяком случае, IDispatch должен работать независимо от того, что из-за того, что использует VB6.
IDispatch
, а затем передавая его вwin32com.client.Dispatch()
получаете объект COM с поздней привязкой, который позволяет мне получить доступ к нужным мне данным. Однако я получаю только один вызовInfoMessage
с объектом Error.Connection.Errors
. Я не уверен, как это поможет вам отслеживать прогресс, хотя.