Exécuter un objet COM basé sur dll en dehors du processus de 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 la base de connaissances d’origine : 198891

Résumé

Microsoft SQL Server permet 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 de la mémoire du processus SQL Server, mais qu’ils disposent également d’un accès complet à cet espace d’adressage mémoire. Par conséquent, un objet COM chargé dans l’espace de traitement SQL Server doit respecter les mêmes règles que n’importe quel fichier DLL. Il est possible qu’un objet COM remplace la mémoire dans le processus SQL Server ou fuite de ressources, ce qui provoque une instabilité.

Si vous pensez qu’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 d’emplacement dans le système d’exploitation a permis d’exécuter un objet COM basé sur dll en dehors de l’espace de traitement SQL Server.

Le processus d’exécution d’un objet COM basé sur dll en dehors de l’espace d’adressage de l’application main 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 en toute transparence vers le client, qui dans ce cas est le SQL Server. Cet exécutable peut accepter simultanément plusieurs demandes d’interface/méthode. Une fois l’utilisation de l’interface terminée, le Gestionnaire de contrôle de service (SCM) DCOM 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 en cours de création dans l’espace de traitement SQL Server, qu’il soit instancié via sp_OACreate ou une procédure stockée étendue.

Plus d’informations

Voici des informations sur les deux méthodes de base que vous pouvez utiliser pour instancier l’objet COM hors processus.

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é en cours. Toutefois, il existe un troisième paramètre facultatif pour cette procédure que vous pouvez utiliser pour indiquer le contexte de création de 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 que l’objet est exécuté à l’intérieur ou à l’extérieur 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 une syntaxe similaire à l’exemple suivant pour informer explicitement DCOM d’exécuter l’objet COM hors processus à l’aide de la sp_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 de CoCreateInstance ou CoCreateInstanceEx peut être remplacé par CLSCTX_LOCAL_SERVER. Cela est illustré dans l’exemple de code suivant à l’aide de CoCreateInstance:

    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 la forme sous OLEComponent.ObjectTous les objets. Sélectionnez l’objet COM, puis, dans le menu Objet , sélectionnez CoCreateInstance Indicateurs. Assurez-vous que seul CLSCTX_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 de charger le fichier dllhost.exe et d’amener la DLL COM dans son espace de processus.

  • Procédez comme suit pour mettre à jour manuellement le Registre.

    Avertissement

    De graves problèmes peuvent se produire si vous vous trompez en modifiant le Registre à l’aide de l’Éditeur du Registre ou toute autre méthode. 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.

    1. 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
      
    2. Vous pouvez utiliser l’identificateur programmatique pour rechercher l’identificateur de classe d’un objet COM.

      Ouvrez le registre Rédacteur (regedit.exe) et sous la HKEY_CLASSES_ROOT clé, utilisez la Find méthode pour rechercher une clé portant le nom de votre <OLEComponent.Object>. Vous le trouverez à d’autres niveaux, mais il doit se trouver au niveau directement sous .HKEY_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 se trouve un titre nommé Default. Les données de cette clé doivent être au format suivant :

      {59F929A0-74D8-11D2-8CBC-08005A390B09}

      Notez cette valeur ou copiez-la dans le Bloc-notes. Incluez les crochets.

    3. Accédez sous la HKEY_CLASSES_ROOT\CLSID clé et recherchez la sous-clé avec ce numéro GUID. Après avoir mis en surbrillance la HKEY_CLASSES_ROOT\CLSID clé, vous pouvez utiliser la fonction Rechercher dans le registre Rédacteur (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, case activée cette valeur GUID. Cela doit être différent de ce que vous avez noté à l’étape 1. Sinon, vous avez le GUID TypeLib et non le GUID de l’objet COM. La sous-clé ProgID aura la valeur OLEComponent.Object.1. Celui de la fin est destiné uniquement à cet exemple et est utilisé pour les informations de gestion de version.

    4. Sous la sous-clé InprocServer32 du GUID, assurez-vous qu’une ThreadingModel valeur existe et qu’elle est définie sur Both ou Free pour vous assurer que le marshaling comprend le modèle de thread de l’objet COM pour permettre l’exécution de COM en dehors de SQL Server espace de processus. S’il n’y a pas de ThreadingModel valeur ou s’il est défini sur Appartement, l’instanciation de l’objet COM peut ne pas être cohérente.

      Remarque

      Si vous ajoutez la ThreadingModel valeur, veillez à tester votre objet COM avant d’implémenter.

    5. Mettez en surbrillance le numéro/sous-clé GUID sous la HKEY_CLASSES_ROOT\CLSID clé. Dans le menu Modifier , sélectionnez Nouveau, puis Valeur de chaîne. Sous la colonne Nom , tapez AppID.

    6. 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 accolades, 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.

    7. Ajoutez une nouvelle sous-clé sous et HKEY_CLASSES_ROOT\AppID définissez son nom sur le même identificateur de classe ou numéro GUID avec les crochets insérés à l’étape précédente.

    8. Mettez en surbrillance le nom du GUID. Dans le menu Modifier , sélectionnez Nouveau, puis Valeur de chaîne. Sous la colonne Nom , tapez dllSurrogate.

      Laissez la colonne Données vide pour cette valeur. Étant donné que la colonne de données est vide, DCOM doit exécuter le fichier exécutable par défaut, dllhost.exeet charger l’objet COM dans son espace de processus.

    9. 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ée . Cliquez sur l’onglet Propriétés par défaut et assurez-vous que l’option Activer la fonctionnalité COM distribuée sur cet ordinateur est sélectionnée. Si ce n’est pas le cas, sélectionnez-le, puis sélectionnez Appliquer.

    10. Assurez-vous 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 de manière incorrecte, 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 inscrite

      Informations 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 serveur

    11. Testez et vérifiez s’il exécute le fichier dllhost.exe et charge 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 est en cours d’exécution. 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 identificateurs de processus (PID). Dans le script Transact-SQL où sp_OACreate est exécuté et après l’exécution de cet appel, mais avant la fin du script, utilisez ce qui suit pour retarder l’exécution 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 dllhost.exe PID. Réexécuteztlist.exe et transmettez le PID en tant que paramètre. Affiche les DLL chargées dans l’espace de traitementdllhost.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 detlist.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 Connection est créé en dehors de l’espace de traitement SQL Server. Cette instantané à l’aide detlist.exe a été effectuée lorsque l’objet COM existait dans l’espace de traitement 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
      

References

Procédures stockées OLE Automation (Transact-SQL)