Obtener mensajes de servidor SQL usando ADO y Win32com
-
28-10-2019 - |
Pregunta
Actualmente estoy tratando de escribir una herramienta que sea muy fácil para un usuario de alfabetización que no sea de empleo hacer una copia de seguridad de una base de datos de SQL Server.
Para hacer esto, espero usar una mezcla interesante de Ado, Win32com y ADODBAPI. Actualmente puedo conectarme fácilmente al servidor y emite un BACKUP DATABASE
Comando T-SQL.
Esto funciona, sin embargo, a menudo lleva mucho tiempo el comando ejecutar (especialmente en bases de datos muy grandes). Con este fin esperaba capturar y analizar el InfoMessage
evento (MSDN) y úselo para mostrar una barra/contador porcentual.
Esto también lo he logrado, ahora estoy atrapado en el obstáculo final, analizando el evento. los MSDN Los documentos dicen que debería ser aprobado cualquiera Error o Errores objeto en el pError
parámetro. Sin embargo, Win32com me pasa un PyIUnknown
Objeto con el que no sé cómo tratar.
A continuación se muestra el código que he escrito hasta ahora:
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'
¿Alguien puede extraer los mensajes informativos de los eventos?
Esto es implementado en VB (Pienso)
Para obtener un ejemplo de uno de estos mensajes, inicie SQL Server Management Studio y ejecute una copia de seguridad utilizando un script (puede generar el script usando el diálogo de copia de seguridad y el botón de script en la parte superior izquierda). Notará que cuando ejecute el script, el cuadro Mensajes poblará con el porcentaje de mensajes completos. Estos son lo que quiero.
Editar:
A continuación se muestra el nuevo código que estoy usando para interrogar los objetos COM que se pasan al InfoMessage
. Esto se basa en la respuesta a continuación, la pongo aquí en caso de que alguien más la necesite.
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
Solución
Leyendo msdn, solo parece Error
Los objetos deben pasar a los manejadores de eventos. Si hay múltiples errores, puede obtenerlos del Errors
recopilación de tu Connection
objeto. Por lo tanto, solo debe esperar que los objetos de error pasen a InfoMessage()
. Si obtienes pyiunknown en su lugar, tal vez puedas intentar llamar QueryInterface()
¿Sobre él y solicitar Idispatch? También puede intentar solicitar la interfaz personalizada específica Error
Usos, pero no recuerdo si PythOncom admite interfaces personalizadas (es decir, no idispatch), y mi internet está gastando en este momento, por lo que no puedo verificar, por lo que tendrá que verificarlo usted mismo. De todos modos, Idispatch debería funcionar sin importar qué, ya que eso es lo que usa VB6.