Partager via


Enregistrer un évaluateur d’expressions

Important

Dans Visual Studio 2015, cette façon d’implémenter des évaluateurs d’expression est déconseillée. Pour plus d’informations sur l’implémentation d’évaluateurs d’expression CLR, consultez l’exemple d’évaluateur d’expression CLR et d’évaluateur d’expression managée.

L’évaluateur d’expression (EE) doit s’inscrire en tant que fabrique de classes avec l’environnement COM Windows et Visual Studio. Un EE est configuré en tant que DLL afin qu'il soit injecté dans l’espace d’adressage du moteur de débogage (DE) ou dans l’espace d’adressage de Visual Studio, selon l’entité qui l’instancie.

Évaluateur d’expression de code managé

Un environnement EE de code managé est implémenté en tant que bibliothèque de classes, qui est une DLL qui s’inscrit auprès de l’environnement COM, généralement démarrée par un appel au programme VSIP, regpkg.exe. Le processus réel d’écriture des clés de Registre pour l’environnement COM est géré automatiquement.

Une méthode de la classe principale est marquée avec ComRegisterFunctionAttribute, indiquant que la méthode doit être appelée lorsque la DLL est inscrite auprès de COM. Cette méthode d’inscription, souvent appelée RegisterClass, effectue la tâche d’inscription de la DLL auprès de Visual Studio. Un UnregisterClass correspondant (marqué avec le ComUnregisterFunctionAttribute) annule les effets de RegisterClass lors de la désinstallation de la DLL. Les mêmes entrées de Registre sont effectuées que pour un EE écrit dans du code non managé ; la seule différence est qu’il n’existe aucune fonction d’assistance, telle que SetEEMetric, pour effectuer cette tâche. Voici un exemple de processus d’inscription et d’annulation de l’inscription.

Example

La fonction suivante montre comment un EE de code managé s'enregistre et se désenregistre dans Visual Studio.

namespace EEMC
{
    [GuidAttribute("462D4A3D-B257-4AEE-97CD-5918C7531757")]
    public class EEMCClass : IDebugExpressionEvaluator
    {
        #region Register and unregister.
        private static Guid guidMycLang = new Guid("462D4A3E-B257-4AEE-97CD-5918C7531757");
        private static string languageName = "MyC";
        private static string eeName = "MyC Expression Evaluator";

        private static Guid guidMicrosoftVendor = new Guid("994B45C4-E6E9-11D2-903F-00C04FA302A1");
        private static Guid guidCOMPlusOnlyEng = new Guid("449EC4CC-30D2-4032-9256-EE18EB41B62B");
        private static Guid guidCOMPlusNativeEng = new Guid("92EF0900-2251-11D2-B72E-0000F87572EF");

        /// <summary>
        /// Register the expression evaluator.
        /// Set "project properties/configuration properties/build/register for COM interop" to true.
        /// </summary>
         [ComRegisterFunctionAttribute]
        public static void RegisterClass(Type t)
        {
            // Get Visual Studio version (set by regpkg.exe)
            string hive = Environment.GetEnvironmentVariable("EnvSdk_RegKey");
            string s = @"SOFTWARE\Microsoft\VisualStudio\"
                        + hive
                        + @"\AD7Metrics\ExpressionEvaluator";

            RegistryKey rk = Registry.LocalMachine.CreateSubKey(s);
            if (rk == null)  return;

            rk = rk.CreateSubKey(guidMycLang.ToString("B"));
            rk = rk.CreateSubKey(guidMicrosoftVendor.ToString("B"));
            rk.SetValue("CLSID", t.GUID.ToString("B"));
            rk.SetValue("Language", languageName);
            rk.SetValue("Name", eeName);

            rk = rk.CreateSubKey("Engine");
            rk.SetValue("0", guidCOMPlusOnlyEng.ToString("B"));
            rk.SetValue("1", guidCOMPlusNativeEng.ToString("B"));
        }
        /// <summary>
        /// Unregister the expression evaluator.
        /// </summary>
         [ComUnregisterFunctionAttribute]
        public static void UnregisterClass(Type t)
        {
            // Get Visual Studio version (set by regpkg.exe)
            string hive = Environment.GetEnvironmentVariable("EnvSdk_RegKey");
            string s = @"SOFTWARE\Microsoft\VisualStudio\"
                        + hive
                        + @"\AD7Metrics\ExpressionEvaluator\"
                        + guidMycLang.ToString("B");
            RegistryKey key = Registry.LocalMachine.OpenSubKey(s);
            if (key != null)
            {
                key.Close();
                Registry.LocalMachine.DeleteSubKeyTree(s);
            }
        }
    }
}

Évaluateur d’expression de code non managé

La DLL EE implémente la DllRegisterServer fonction pour s’inscrire auprès de l’environnement COM ainsi que Visual Studio.

Note

Vous trouverez l’exemple de code MyCEE dans le fichier dllentry.cpp, qui se trouve dans l’installation de VSIP sous EnVSDK\MyCPkgs\MyCEE.

Processus du serveur DLL

Lors de l’inscription de l’EE, le serveur DLL :

  1. Inscrit sa fabrique CLSID de classes conformément aux conventions COM normales.

  2. Appelle la fonction d'assistance SetEEMetric pour enregistrer auprès de Visual Studio les métriques ÉE présentées dans le tableau suivant. La fonction SetEEMetric et les métriques spécifiées comme suit font partie de la bibliothèque dbgmetric.lib . Pour plus d’informations, consultez les assistants du Kit de développement logiciel (SDK) pour le débogage.

    Unité de mesure Descriptif
    metricCLSID CLSID de l'usine de classes EE
    metricName Nom de l’EE sous forme de chaîne affichable
    metricLanguage Nom de la langue que l’EE est conçue pour évaluer
    metricEngine GUIDdes moteurs de débogage (DE) qui fonctionnent avec cet EE

    Note

    Le metricLanguage``GUID identifie la langue par son nom, mais c'est l'argument guidLang de SetEEMetric qui sélectionne la langue. Lorsque le compilateur génère le fichier d’informations de débogage, il doit écrire le fichier approprié guidLang afin que le DE sache quel EE utiliser. Le DE demande généralement le fournisseur de symboles pour cette langue GUID, qui est stocké dans le fichier d’informations de débogage.

  3. S’inscrit auprès de Visual Studio en créant des clés sous HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\X.Y, où X.Y est la version de Visual Studio à inscrire.

Example

La fonction suivante montre comment un code non managé (C++) EE inscrit et désinscrit lui-même avec Visual Studio.

/*---------------------------------------------------------
  Registration
-----------------------------------------------------------*/
#ifndef LREGKEY_VISUALSTUDIOROOT
    #define LREGKEY_VISUALSTUDIOROOT L"Software\\Microsoft\\VisualStudio\\8.0"
#endif

static HRESULT RegisterMetric( bool registerIt )
{
    // check where we should register
    const ULONG cchBuffer = _MAX_PATH;
    WCHAR wszRegistrationRoot[cchBuffer];
    DWORD cchFreeBuffer = cchBuffer - 1;
    wcscpy(wszRegistrationRoot, LREGKEY_VISUALSTUDIOROOT_NOVERSION);
    wcscat(wszRegistrationRoot, L"\\");

    // this is Environment SDK specific
    // we check for  EnvSdk_RegKey environment variable to
    // determine where to register
    DWORD cchDefRegRoot = lstrlenW(LREGKEY_VISUALSTUDIOROOT_NOVERSION) + 1;
    cchFreeBuffer = cchFreeBuffer - cchDefRegRoot;
    DWORD cchEnvVarRead = GetEnvironmentVariableW(
        /* LPCTSTR */ L"EnvSdk_RegKey", // environment variable name
        /* LPTSTR  */ &wszRegistrationRoot[cchDefRegRoot],// buffer for variable value
        /* DWORD   */ cchFreeBuffer);// size of buffer
    if (cchEnvVarRead >= cchFreeBuffer)
        return E_UNEXPECTED;
    // If the environment variable does not exist then we must use
    // LREGKEY_VISUALSTUDIOROOT which has the version number.
    if (0 == cchEnvVarRead)
        wcscpy(wszRegistrationRoot, LREGKEY_VISUALSTUDIOROOT);

    if (registerIt)
    {
        SetEEMetric(guidMycLang,
                    guidMicrosoftVendor,
                    metricCLSID,
                    CLSID_MycEE,
                    wszRegistrationRoot );
        SetEEMetric(guidMycLang,
                    guidMicrosoftVendor,
                    metricName,
                    GetString(IDS_INFO_MYCDESCRIPTION),
                    wszRegistrationRoot );
        SetEEMetric(guidMycLang,
                    guidMicrosoftVendor,
                    metricLanguage, L"MyC",
                    wszRegistrationRoot);

        GUID engineGuids[2];
        engineGuids[0] = guidCOMPlusOnlyEng;
        engineGuids[1] = guidCOMPlusNativeEng;
        SetEEMetric(guidMycLang,
                    guidMicrosoftVendor,
                    metricEngine,
                    engineGuids,
                    2,
                    wszRegistrationRoot);
    }
    else
    {
        RemoveEEMetric( guidMycLang,
                        guidMicrosoftVendor,
                        metricCLSID,
                        wszRegistrationRoot);
        RemoveEEMetric( guidMycLang,
                        guidMicrosoftVendor,
                        metricName,
                        wszRegistrationRoot );
        RemoveEEMetric( guidMycLang,
                        guidMicrosoftVendor,
                        metricLanguage,
                        wszRegistrationRoot );
        RemoveEEMetric( guidMycLang,
                        guidMicrosoftVendor,
                        metricEngine,
                        wszRegistrationRoot );
    }

    return S_OK;
}