Ottenere messaggi SQL Server utilizzando ADO e Win32Com
-
28-10-2019 - |
Domanda
Attualmente sto cercando di scrivere uno strumento che renderà molto facile per un utente alfabetizzato non computer di eseguire il backup di un database SQL Server.
Per fare questo spero di usare un interessante mix di Ado, Win32Com e Adodbapi. Attualmente posso facilmente connettermi al server e emettere a BACKUP DATABASE
Comando T-SQL.
Funziona, tuttavia spesso ci vuole molto tempo per l'esecuzione del comando (specialmente su database molto grandi). A tal fine speravo di catturare e analizzare il InfoMessage
evento (Msdn) e usalo per mostrare una barra/contatore percentuale.
Anche questo sono riuscito, ora sono bloccato all'ostacolo finale, analizzando l'evento. Il Msdn I dottori dicono che dovrei essere superato uno Errore o Errori oggetto nel pError
parametro. Tuttavia Win32Com mi passa a PyIUnknown
oggetto che non so come affrontare.
Di seguito è riportato il codice che ho scritto finora:
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'
Qualcuno può estrarre i messaggi informativi dagli eventi?
Questo è implementato in VB (Penso)
Per un esempio di uno di questi messaggi avviare SQL Server Management Studio ed eseguire un backup utilizzando uno script (è possibile generare lo script utilizzando il dialogo di backup e il pulsante di script in alto a sinistra). Noterai che quando si esegue lo script, la casella dei messaggi popolerà con messaggi completi percentuali. Questi sono quello che voglio.
Modificare:
Di seguito è riportato il nuovo codice che sto usando per interrogare gli oggetti COM che vengono passati al InfoMessage
. Questo si basa sulla risposta qui sotto, lo metto qui nel caso in cui qualcun altro ne abbia bisogno.
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
Soluzione
Leggendo MSDN, sembra solo Error
Gli oggetti dovrebbero essere passati ai gestori dell'evento. Se ci sono più errori, puoi ottenerli da Errors
collezione del tuo Connection
oggetto. Quindi dovresti aspettarti solo che gli oggetti di errore vengano passati InfoMessage()
. Se invece si ottiene Pyiunknown, forse puoi provare a chiamare QueryInterface()
su di esso e richiedi Idispatch? Puoi anche provare a richiedere l'interfaccia personalizzata specifica Error
Usi, ma non ricordo se Pythoncom supporta interfacce personalizzate (cioè non idispatch) e la mia Internet sta strisciando in questo momento, quindi non posso controllare, quindi dovrai controllarlo da solo. Ad ogni modo, IdisPatch dovrebbe funzionare, non importa quale, dato che è ciò che VB6 usa.