Freigeben über


Auswerten eines Überwachungsausdrucks

Wichtig

Seit Visual Studio 2015 ist diese Art der Implementierung von Ausdrucksauswertungen veraltet. Informationen zum Implementieren von CLR-Ausdrucksauswertungen finden Sie unter CLR-Ausdrucksauswertungen und Beispiel für die Auswertung verwalteter Ausdrücke.

Wenn Visual Studio bereit ist, den Wert eines Überwachungsausdrucks anzuzeigen, ruft es EvaluateSync auf, was wiederum EvaluateSync aufruft. Dieser Prozess erzeugt ein IDebugProperty2 -Objekt, das den Wert und typ des Ausdrucks enthält.

In dieser Implementierung IDebugParsedExpression::EvaluateSyncwird der Ausdruck analysiert und gleichzeitig ausgewertet. Diese Implementierung führt die folgenden Aufgaben aus:

  1. Analysiert und wertet den Ausdruck aus, um ein generisches Objekt zu erzeugen, das den Wert und seinen Typ enthält. In C# wird dies als object eine Weile in C++ dargestellt, dies wird als ein VARIANT.

  2. Instanziiert eine Klasse (in diesem Beispiel aufgerufen CValueProperty ), die die IDebugProperty2 Schnittstelle implementiert und in der Klasse speichert, die zurückgegeben werden soll.

  3. Gibt die IDebugProperty2 Schnittstelle aus dem CValueProperty-Objekt zurück.

Verwalteter Code

Dies ist eine Implementierung des IDebugParsedExpression::EvaluateSync verwalteten Codes. Die Hilfsmethode Tokenize analysiert den Ausdruck in eine Analysestruktur. Die Hilfsfunktion EvalToken konvertiert das Token in einen Wert. Die Hilfsfunktion FindTerm durchläuft rekursiv die Analysestruktur und ruft EvalToken für jeden Knoten, der einen Wert darstellt, und wendet alle Vorgänge (Addition oder Subtraktion) im Ausdruck an.

namespace EEMC
{
    public class CParsedExpression : IDebugParsedExpression
    {
        public HRESULT EvaluateSync(
            uint evalFlags,
            uint timeout,
            IDebugSymbolProvider provider,
            IDebugAddress address,
            IDebugBinder binder,
            string resultType,
            out IDebugProperty2 result)
        {
            HRESULT retval = COM.S_OK;
            this.evalFlags = evalFlags;
            this.timeout = timeout;
            this.provider = provider;
            this.address = address;
            this.binder = binder;
            this.resultType = resultType;

            try
            {
                IDebugField field = null;
                // Tokenize, then parse.
                tokens = Tokenize(expression);
                result = new CValueProperty(
                        expression,
                        (int) FindTerm(EvalToken(tokens[0], out field),1),
                        field,
                        binder);
            }
            catch (ParseException)
            {
                result = new CValueProperty(expression, "Huh?");
                retval = COM.E_INVALIDARG;
            }
            return retval;
        }
    }
}

Nicht verwalteter Code

Dies ist eine Implementierung des IDebugParsedExpression::EvaluateSync nicht verwalteten Codes. Die Hilfsfunktion Evaluate analysiert und wertet den Ausdruck aus und gibt einen VARIANT Haltewert für den resultierenden Wert zurück. Die Hilfsfunktion VariantValueToProperty bündelt das VARIANT Objekt in ein CValueProperty Objekt.

STDMETHODIMP CParsedExpression::EvaluateSync(
    in  DWORD                 evalFlags,
    in  DWORD                 dwTimeout,
    in  IDebugSymbolProvider* pprovider,
    in  IDebugAddress*        paddress,
    in  IDebugBinder*         pbinder,
    in  BSTR                  bstrResultType,
    out IDebugProperty2**     ppproperty )
{
    // dwTimeout parameter is ignored in this implementation.
    if (pprovider == NULL)
        return E_INVALIDARG;

    if (paddress == NULL)
        return E_INVALIDARG;

    if (pbinder == NULL)
        return E_INVALIDARG;

    if (ppproperty == NULL)
        return E_INVALIDARG;
    else
        *ppproperty = 0;

    HRESULT hr;
    VARIANT value;
    BSTR    bstrErrorMessage = NULL;
    hr = ::Evaluate( pprovider,
                     paddress,
                     pbinder,
                     m_expr,
                     &bstrErrorMessage,
                     &value );
    if (hr != S_OK)
    {
        if (bstrErrorMessage == NULL)
            return hr;

        //we can display better messages ourselves.
        HRESULT hrLocal = S_OK;
        VARIANT varType;
        VARIANT varErrorMessage;

        VariantInit( &varType );
        VariantInit( &varErrorMessage );
        varErrorMessage.vt      = VT_BSTR;
        varErrorMessage.bstrVal = bstrErrorMessage;

        CValueProperty* valueProperty = new CValueProperty();
        if (valueProperty != NULL)
        {
            hrLocal = valueProperty->Init(m_expr, varType, varErrorMessage);
            if (SUCCEEDED(hrLocal))
            {
                hrLocal = valueProperty->QueryInterface( IID_IDebugProperty2,
                        reinterpret_cast<void**>(ppproperty) );
            }
        }

        VariantClear(&varType);
        VariantClear(&varErrorMessage); //frees BSTR
        if (!valueProperty)
            return hr;
        valueProperty->Release();
        if (FAILED(hrLocal))
            return hr;
    }
    else
    {
        if (bstrErrorMessage != NULL)
            SysFreeString(bstrErrorMessage);

        hr = VariantValueToProperty( pprovider,
                                     paddress,
                                     pbinder,
                                     m_radix,
                                     m_expr,
                                     value,
                                     ppproperty );
        VariantClear(&value);
        if (FAILED(hr))
            return hr;
    }

    return S_OK;
}