Obtenir des messages SQL Server à l'aide d'ADO et de win32com
-
28-10-2019 - |
Question
J'essaie actuellement d'écrire un outil qui permettra à un utilisateur non averti en informatique de sauvegarder une base de données SQL Server très facilement.
Pour ce faire, j'espère utiliser un mélange intéressant d'ADO, de win32com et d'adodbapi. Actuellement, je peux facilement me connecter au serveur et émettre une commande BACKUP DATABASE
T-SQL.
Cela fonctionne, mais l'exécution de la commande prend souvent beaucoup de temps (surtout sur de très grandes bases de données). À cette fin, j'espérais capturer et analyser l'événement InfoMessage
( MSDN ) et utilisez-le pour afficher une barre / compteur de pourcentage.
Cela, j'ai également réussi, je suis maintenant coincé au dernier obstacle, l'analyse de l'événement. La documentation MSDN dit que je devrais être transmis soit une Erreur soit < un objet href="http://msdn.microsoft.com/en-us/library/ms675299(v=vs.85).aspx" rel="nofollow noreferrer"> Erreurs dans le paramètre pError
. Cependant win32com me passe un objet PyIUnknown
que je ne sais pas comment gérer.
Voici le code que j'ai écrit jusqu'à présent:
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'
Quelqu'un peut-il extraire les messages d'information des événements?
Ceci est implémenté dans VB (je pense )
Pour un exemple de l'un de ces messages, démarrez SQL Server Management Studio et exécutez une sauvegarde à l'aide d'un script (vous pouvez générer le script à l'aide de la boîte de dialogue de sauvegarde et du bouton de script en haut à gauche). Vous remarquerez que lorsque vous exécutez le script, la boîte de messages se remplit de messages en pourcentage achevé. Voilà ce que je veux.
Modifier:
Vous trouverez ci-dessous le nouveau code que j'utilise pour interroger les objets COM qui sont passés au InfoMessage
. Ceci est basé sur la réponse ci-dessous, je la mets ici au cas où quelqu'un d'autre en aurait besoin.
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
La solution
En lisant MSDN, il semble que seuls les objets Error
devraient être passés aux gestionnaires d'événements.S'il y a plusieurs erreurs, vous pouvez les récupérer à partir de la collection Errors
de votre objet Connection
.Vous ne devez donc vous attendre à ce que les objets Error soient transmis à InfoMessage()
.Si vous obtenez PyIUnknown à la place, vous pouvez peut-être essayer d'appeler QueryInterface()
dessus et demander IDispatch?Vous pouvez également essayer de demander l'interface personnalisée spécifique utilisée par Error
, mais je ne me souviens pas si Pythoncom prend en charge les interfaces personnalisées (c'est-à-dire non IDispatch), et mon Internet est en train d'explorer en ce moment, je ne peux donc pas vérifier, vous devrezvérifiez cela vous-même.Quoi qu'il en soit, IDispatch devrait fonctionner quoi qu'il arrive, puisque c'est ce que VB6 utilise.