Partilhar via


Registar um avaliador de expressões

Importante

No Visual Studio 2015, essa maneira de implementar avaliadores de expressão foi preterida. Para obter informações sobre como implementar avaliadores de expressão CLR, consulte Avaliadores de expressão CLR e Exemplo de avaliador de expressão gerenciado.

O avaliador de expressão (EE) deve registrar-se como uma fábrica de classes com o ambiente COM do Windows e o Visual Studio. Um EE é implementado como uma DLL para ser injetado no espaço de endereço do motor de depuração (DE) ou no espaço de endereço do Visual Studio, dependendo de qual entidade instancia o EE.

Avaliador de expressão de código gerenciado

Um código gerenciado EE é implementado como uma biblioteca de classes, que é uma DLL que se registra com o ambiente COM, normalmente iniciado por uma chamada para o programa VSIP, regpkg.exe. O processo real de escrever as chaves do Registro para o ambiente COM é tratado automaticamente.

Um método da classe principal é marcado com ComRegisterFunctionAttribute, indicando que o método deve ser chamado quando a DLL está sendo registrada com COM. Esse método de registro, geralmente chamado de RegisterClass, executa a tarefa de registrar a DLL com o Visual Studio. Um correspondente UnregisterClass (marcado com o ComUnregisterFunctionAttribute), desfaz os efeitos de RegisterClass quando a DLL é desinstalada. As mesmas entradas de registo são feitas como para um EE escrito em código não gerido; a única diferença é que não existe uma função auxiliar como SetEEMetric para fazer o trabalho para si. Segue-se um exemplo do processo de registo e cancelamento de registo.

Example

A função a seguir mostra como um código gerenciado EE registra e cancela o registro com o 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);
            }
        }
    }
}

Avaliador de expressão de código não gerenciado

A DLL EE implementa a DllRegisterServer função para registrar-se com o ambiente COM, bem como Visual Studio.

Observação

Você pode encontrar o código de registo de exemplo MyCEE no arquivo dllentry.cpp, que está localizado na instalação do VSIP em EnVSDK\MyCPkgs\MyCEE.

Processo do servidor DLL

Ao registar o EE, o servidor DLL:

  1. Regista a sua fábrica de classes CLSID de acordo com as convenções normais do COM.

  2. Chama a função SetEEMetric auxiliar para registrar no Visual Studio as métricas EE mostradas na tabela a seguir. A função SetEEMetric e as métricas especificadas a seguir fazem parte da biblioteca dbgmetric.lib . Consulte os auxiliares do SDK para depuração para obter detalhes.

    Métrico Description
    metricCLSID CLSID da fábrica da classe EE
    metricName Nome do EE como uma cadeia de caracteres exibível
    metricLanguage O nome da língua que a EE foi concebida para avaliar
    metricEngine GUIDs dos mecanismos de depuração (DE) que funcionam com este EE

    Observação

    O metricLanguage``GUID identifica o idioma pelo nome, mas é o guidLang argumento para SetEEMetric que seleciona o idioma. Quando o compilador gera o arquivo de informações de depuração, ele deve escrever o apropriado guidLang para que o DE saiba qual EE usar. O DE normalmente solicita ao provedor de símbolos esse idioma GUID, que é armazenado no arquivo de informações de depuração.

  3. Registra-se com o Visual Studio criando chaves em HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\X.Y, onde X.Y é a versão do Visual Studio para registrar.

Example

A função a seguir mostra como um código não gerenciado (C++) EE registra e cancela o registro com o 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;
}