Exécuter un objet COM basé sur DLL en dehors du processus SQL Server
Cet article explique comment exécuter un objet COM basé sur DLL en dehors du processus SQL Server.
Version du produit d’origine : SQL Server
Numéro de base de connaissances d’origine : 198891
Résumé
Microsoft SQL Server offre la possibilité de charger et d’exécuter des objets COM (Component Object Model) personnalisés via un ensemble de procédures stockées OLE Automation ou via des procédures stockées étendues. Par défaut, les objets COM basés sur DLL sont chargés comme dans le serveur de processus, ce qui signifie que les objets COM ne sont pas seulement chargés dans l’espace d’adressage mémoire du processus SQL Server, mais qu’ils ont également un accès total à cet espace d’adressage mémoire. Par conséquent, un objet COM chargé dans l’espace de processus SQL Server doit respecter les mêmes règles que n’importe quel fichier DLL. Il est possible qu’un objet COM puisse remplacer la mémoire au sein du processus SQL Server ou fuiter des ressources, ce qui provoque une instabilité.
Si un objet COM peut affecter la robustesse du processus SQL Server, vous pouvez utiliser les étapes décrites dans cet article pour instancier l’objet COM en dehors de l’espace de processus SQL Server. L’implémentation de la spécification DCOM (Distributed Component Object Model) de La transparence de l’emplacement dans le système d’exploitation a permis d’exécuter un objet COM basé sur DLL en dehors de l’espace de processus SQL Server.
Le processus d’exécution d’un objet COM basé sur DLL en dehors de l’espace d’adressage de l’application principale est appelé communication à distance. La communication à distance nécessite qu’un autre exécutable soit un processus de substitution à la place de l’exécutable SQL Server. L’exécutable par défaut utilisé par le Gestionnaire de contrôle de service DCOM (rpcss.exe) est nommé dllhost.exe. La structure de prise en charge DCOM utilise le fichier dllhost.exe pour charger la DLL dans son espace de processus, puis utilise des paires proxy/stub pour marshaler l’interface demandée de manière transparente vers le client, ce qui, dans ce cas, est sql Server. Cet exécutable peut accepter simultanément plusieurs demandes d’interface/méthode. Une fois l’interface utilisée, le gestionnaire de contrôle de service DCOM (SCM) gère le nettoyage et le déchargement du fichier dllhost.exe . Les objets COM ne doivent pas être censés conserver les informations d’état entre les instanciations.
Les étapes suivantes peuvent s’appliquer à n’importe quel objet COM basé sur DLL qui est créé dans l’espace de processus SQL Server, qu’il soit instancié ou sp_OACreate
une procédure stockée étendue.
Plus d’informations
Des informations sur les deux méthodes de base que vous pouvez utiliser pour instancier l’objet COM hors processus suivent.
Le client COM demande la communication à distance de l’objet
En modifiant la façon dont vous appelez l’objet COM, vous pouvez demander que l’objet soit créé en dehors de l’espace d’adressage SQL Server.
Si l’objet COM est chargé à l’aide de la
sp_OACreate
procédure, par défaut, il est chargé dans le processus. Toutefois, il existe un troisième paramètre facultatif pour cette procédure que vous pouvez utiliser pour indiquer le contexte d’où créer l’objet. Si ce paramètre n’est pas spécifié, le paramètre par défaut de cinq (5) est utilisé, ce qui signifie exécuter l’objet à l’intérieur ou en dehors du processus. Vous devez remplacer le paramètre par quatre (4), ce qui indique à DCOM que ce composant doit s’exécuter en tant qu’exécutable local. Utilisez la syntaxe similaire à l’exemple suivant pour informer explicitement DCOM d’exécuter l’objet COM hors processus à l’aide de lasp_OACreate
procédure stockée :DECLARE @object int DECLARE @hr int EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
Si l’objet COM est créé dans une procédure stockée étendue, le troisième paramètre ou
CoCreateInstance
CoCreateInstanceEx
peut être modifié enCLSCTX_LOCAL_SERVER
. Ceci est illustré dans l’exemple de code suivant à l’aideCoCreateInstance
de :HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&piunknown);
Modifier le Registre pour forcer la communication à distance de l’objet
Si vous ne pouvez pas modifier le client COM pour demander que l’objet soit créé hors processus, deux méthodes différentes existent pour forcer la création de l’objet hors processus.
Utilisez la visionneuse d’objets OLE/COM (oleview.exe) fournie avec Visual C++ et recherchez le ProgID sous
OLEComponent.Object
Tous les objets. Sélectionnez l’objet COM, puis dans le menu Objet , sélectionnezCoCreateInstance
Indicateurs. Assurez-vous que seulCLSCTX_LOCAL_SERVER
est sélectionné. Ensuite, sous les onglets Implémentation et Serveur Inproc, sélectionnez Utiliser le processus de substitution et laissez le chemin d’accès au substitut personnalisé vide, ce qui permet au fichier dllhost.exe d’être chargé et la DLL COM apportée dans son espace de processus.Procédez comme suit pour mettre à jour manuellement le Registre.
Avertissement
Des problèmes graves peuvent survenir si vous modifiez le Registre incorrectement à l’aide de l’Éditeur du Registre ou d’un autre procédé. Ces problèmes peuvent nécessiter la réinstallation du système d’exploitation. Microsoft ne peut pas garantir que ces problèmes peuvent être résolus. Vous assumez l’ensemble des risques liés à la modification du Registre.
Obtenez l’identificateur de classe (CLSID) de l’objet COM. Le CLSID est un nombre 128 bits et considéré comme un identificateur global unique (GUID) utilisé pour identifier de manière unique le composant, le module ou le fichier qui contient cet objet COM. Lors de la création d’objets COM à l’aide des procédures stockées OLE Automation, le premier paramètre de la procédure stockée est un identificateur programmatique ou le ProgID de l’objet OLE est utilisé pour dériver le CLSID. Cette chaîne de caractères décrit la classe de l’objet OLE et a la forme suivante :
OLEComponent.Object
Vous pouvez utiliser l’identificateur programmatique pour rechercher l’identificateur de classe d’un objet COM.
Ouvrez l’Éditeur de Registre (regedit.exe) et, sous la
HKEY_CLASSES_ROOT
clé, utilisez laFind
méthode pour localiser une clé avec le nom de votre <objet OLEComponent.Object>. Vous le trouverez à d’autres niveaux, mais il doit être situé au niveau directement sous leHKEY_CLASSES_ROOT
. Après avoir localisé la clé, développez le dossier pour le nom de la clé et vous devez voir une sous-clé nommée CLSID. Sélectionnez ce dossier pour afficher les valeurs de cette clé. Sur le côté droit de l’écran, il s’agit d’un titre nommé Default. Les données de cette clé doivent se trouver sous la forme suivante :{59F929A0-74D8-11D2-8CBC-08005A390B09}
Notez cette valeur ou copiez-la dans le Bloc-notes. Incluez les crochets.
Naviguez sous la
HKEY_CLASSES_ROOT\CLSID
clé et recherchez la sous-clé avec ce numéro GUID. Après avoir mis en surbrillance laHKEY_CLASSES_ROOT\CLSID
clé, vous pouvez utiliser la fonction Rechercher dans l’Éditeur du Registre (sous le menu Modifier ) et coller le GUID dans la boîte de dialogue Rechercher . Vérifiez que vous avez trouvé l’interface appropriée en inspectant la sous-clé InprocServer32 sous cette clé, qui pointe vers l’emplacement de votre fichier DLL COM. S’il existe une clé TypeLib, vérifiez cette valeur GUID. Cela doit être différent de ce que vous avez noté à l’étape 1. Sinon, vous disposez du GUID TypeLib et non du GUID de l’objet COM. La sous-clé ProgID aura la valeurOLEComponent.Object.1
. L’un à la fin est destiné à cet exemple uniquement et est utilisé pour les informations de contrôle de version.Sous la sous-clé InprocServer32 du GUID, assurez-vous qu’une
ThreadingModel
valeur existe et qu’elle est définie sur Les deux ou Free pour vous assurer que le marshaling comprend le modèle de threading de l’objet COM pour permettre l’exécution de COM hors de l’espace de processus SQL Server. S’il n’existe pas deThreadingModel
valeur ou s’il est défini sur Apartment, l’instanciation d’objet COM peut ne pas être cohérente.Note
Si vous ajoutez la
ThreadingModel
valeur, vérifiez que vous testez votre objet COM avant d’implémenter.Mettez en surbrillance le numéro/sous-clé GUID sous la
HKEY_CLASSES_ROOT\CLSID
clé. Dans le menu Modifier , sélectionnez Nouveau, puis sélectionnez Valeur de chaîne. Sous la colonne Name , tapez AppID.Appuyez sur ENTRÉE , puis insérez l’identificateur de classe ou le numéro GUID que vous avez noté à l’étape 1 comme valeur. Le GUID doit se trouver à l’intérieur des crochets courbés comme dans l’exemple suivant :
{59F929A0-74D8-11D2-8CBC-08005A390B09}
L’identificateur d’application AppID est utilisé par DCOM pour associer la DLL à un fichier exécutable.
Ajoutez une nouvelle sous-clé sous le
HKEY_CLASSES_ROOT\AppID
nom et définissez son nom sur le même identificateur de classe ou le même numéro GUID avec les crochets que ceux insérés à l’étape précédente.Mettez en surbrillance le nom du GUID. Dans le menu Modifier , sélectionnez Nouveau, puis sélectionnez Valeur de chaîne. Sous la colonne Name , tapez dllSurrogate.
Laissez la colonne Données vide pour cette valeur. Étant donné que la colonne de données est vide, DCOM informe DCOM d’exécuter le fichier exécutable par défaut, dllhost.exe et de charger l’objet COM dans son espace de processus.
Fermez l’Éditeur du Registre. Cliquez sur Démarrer, puis sélectionnez Exécuter. Dans la boîte de dialogue Exécuter , tapez DCOMCNFG.
Appuyez sur la touche Entrée pour ouvrir la boîte de dialogue Propriétés de configuration COM distribuées. Cliquez sur l’onglet Propriétés par défaut, puis vérifiez que l’option Activer distributed COM sur cet ordinateur est sélectionnée. Si ce n’est pas le cas, sélectionnez-le, puis sélectionnez Appliquer.
Vérifiez que le compte d’utilisateur Windows NT sous lequel SQL Server s’exécute dispose de l’autorisation Contrôle total sur les clés de Registre pour cet objet. Si les autorisations ne sont pas suffisantes ou si les clés de Registre sont entrées incorrectement, les erreurs suivantes peuvent se produire lorsque vous créez l’objet COM :
Informations sur les erreurs OLE Automation
HRESULT : 0x80040154
Source : procédure étendue ODSOLE
Description : Classe non inscriteInformations sur les erreurs OLE Automation
HRESULT : 0x80070005
Source : procédure étendue ODSOLE
Description : l’accès est refusé.Informations sur les erreurs OLE Automation
HRESULT : 0x80080005
Source : procédure étendue ODSOLE
Description : Échec de l’exécution du serveurTestez et vérifiez si cela exécute le fichier dllhost.exe et chargez l’objet COM dans son espace de processus. Cela nécessite que le Kit de ressources Windows NT se trouve sur l’ordinateur Windows NT sur lequel SQL Server s’exécute. Ouvrez une invite de commandes et, à partir de l’invite de commandes, exécutez le fichier tlist.exe , qui affiche tous les processus et leurs identificateurs de processus associés, ou les identificateurs de processus (PID). Dans le script Transact-SQL où
sp_OACreate
est exécuté et après cet appel, mais avant la fin du script, utilisez ce qui suit pour retarder l’achèvement du script pendant 20 secondes supplémentaires :WAITFOR DELAY '000:00:20'
Exécutez le script et accédez immédiatement à l’invite de commandes et exécutez le fichier tlist.exe . Notez le PID dllhost.exe . Réexécutez tlist.exe et transmettez le PID en tant que paramètre. Cela montre les DLL chargées dans l’espace de processus dllhost.exe . L’objet COM basé sur DLL doit être répertorié comme s’exécutant dans ce processus. Une fois le script retourné, l’exécution de tlist.exe révèle à nouveau que le processus dllhost.exe n’est plus en cours d’exécution.
Dans l’exemple de sortie suivant, ADODB. L’objet de connexion est créé en dehors de l’espace de processus SQL Server. Cet instantané utilisant tlist.exe a été effectué pendant que l’objet COM existait dans l’espace de processus dllhost.exe . Notez que le module msado15.dll, qui est le module qui contient l’objet COM, est chargé.
C:\>tlist dllhost 275 dllhost.exe CWD: C:\NT40\system32\ CmdLine: C:\NT40\System32\dllhost.exe {00000514-0000-0010-8000-00AA006D2EA4} -Embedding VirtualSize: 19180 KB PeakVirtualSize: 19180 KB WorkingSetSize: 1780 KB PeakWorkingSetSize: 1780 KB NumberOfThreads: 3 278 Win32StartAddr:0x01001920 LastErr:0x00000000 State:Waiting 215 Win32StartAddr:0x00001b5e LastErr:0x00000000 State:Waiting 253 Win32StartAddr:0x00001b60 LastErr:0x000000cb State:Waiting 4.0.1381.105 shp 0x01000000 dllhost.exe 4.0.1381.130 shp 0x77f60000 ntdll.dll 4.0.1381.121 shp 0x77dc0000 ADVAPI32.dll 4.0.1381.133 shp 0x77f00000 KERNEL32.dll 4.0.1381.133 shp 0x77e70000 USER32.dll 4.0.1381.115 shp 0x77ed0000 GDI32.dll 4.0.1381.131 shp 0x77e10000 RPCRT4.dll 4.0.1381.117 shp 0x77b20000 ole32.dll 6.0.8267.0 shp 0x78000000 MSVCRT.dll 0x1f310000 msado15.dll 2.30.4265.1 shp 0x766f0000 OLEAUT32.dll 4.0.1381.72 shp 0x77bf0000 rpcltc1.dll