Implementazione dell'esempio di modificare i valori
Ogni locale vengono visualizzati nella finestra di locali IDebugProperty2 dispone di un oggetto associato. Questo oggetto di IDebugProperty2 contiene il nome, valore e il tipo locale. Quando un utente modifica il valore di un locale, chiamate IDebugProperty2:: SetValueAsString di Visual Studio per aggiornare il valore locale in memoria. In questo esempio, il locale è rappresentato dalla classe di CFieldProperty che implementa l'interfaccia di IDebugProperty2 .
Nota
Per espressione di controllo e espressioni di Controllo immediato , il valore modificato è rappresentato dalla classe di CValueProperty nell'esempio di MyCEE.Tuttavia, l'implementazione di IDebugProperty2::SetValueAsString è la stessa come illustrato di seguito.
Questa implementazione di IDebugProperty2::SetValueAsString esegue le attività seguenti:
L'espressione viene valutata per produrre un valore.
Associare l'oggetto associato IDebugField alla relativa posizione di memoria e produce IDebugObject un oggetto.
Converte il valore al numero di byte.
Chiama IDebugObject:: SetValue per archiviare i byte in memoria.
Codice gestito
Si tratta di un'implementazione di IDebugProperty2::SetValueAsString nel codice gestito.
[C#]
namespace EEMC
{
public class CFieldProperty : IDebugProperty2
{
public HRESULT SetValueAsString(
string pszValue,
uint dwRadix,
uint dwTimeout)
{
HRESULT hr = COM.E_NOTIMPL;
uint flags = (uint)enum_PARSEFLAGS.PARSE_EXPRESSION;
CParsedExpression parsedExpression =
new CParsedExpression(flags, dwRadix, pszValue);
IDebugProperty2 value;
parsedExpression.EvaluateSync(flags,
dwTimeout,
null,
null,
null,
"string",
out value);
if (value != null)
{
DEBUG_PROPERTY_INFO[] dpi = new DEBUG_PROPERTY_INFO[1];
hr = value.GetPropertyInfo(
(uint)enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE,
dwRadix,
dwTimeout,
null,
0,
dpi);
if (hr == COM.S_OK)
{
hr = Field.SetValue(binder,
field,
dpi[0].bstrValue);
}
}
return hr;
}
}
//----------------------------------------------------------------------------
internal class Field
{
internal static HRESULT SetValue(
IDebugBinder binder,
IDebugField field,
string bstrValue)
{
HRESULT hr = COM.E_FAIL;
uint fieldSize = 0;
Type fieldType = GetType(field, out fieldSize);
if (fieldType != null)
{
FIELD_INFO[] fi = new FIELD_INFO[1];
hr = field.GetInfo((uint)enum_FIELD_INFO_FIELDS.FIF_MODIFIERS, fi);
if (hr != COM.S_OK ||
(fi[0].dwModifiers & (uint)enum_FIELD_MODIFIERS.FIELD_MOD_CONSTANT) != 0)
{
// Couldn't get field info or field is constant and can't be changed.
return COM.E_FAIL;
}
IDebugObject valueObject;
IntPtr pBuffer = new IntPtr();
int bufferSize = 0;
binder.Bind(null, field, out valueObject);
if (valueObject != null)
{
if (fieldType == typeof(sbyte))
{
sbyte value = Convert.ToSByte(bstrValue);
bufferSize = 1;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(short))
{
System.Int16 value = Convert.ToInt16(bstrValue);
bufferSize = 2;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(int))
{
System.Int32 value = Convert.ToInt32(bstrValue);
bufferSize = 4;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(long))
{
System.Int64 value = Convert.ToInt64(bstrValue);
bufferSize = 8;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(byte))
{
byte value = Convert.ToByte(bstrValue);
bufferSize = 1;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(char))
{
char value = Convert.ToChar(bstrValue);
bufferSize = 1;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(bool))
{
bool value = Convert.ToBoolean(bstrValue);
bufferSize = 1;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(uint))
{
System.UInt32 value = Convert.ToUInt32(bstrValue);
bufferSize = 4;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(ulong))
{
System.UInt64 value = Convert.ToUInt64(bstrValue);
bufferSize = 8;
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(float))
{
float value = Convert.ToSingle(bstrValue);
bufferSize = sizeof(float);
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(double))
{
double value = Convert.ToDouble(bstrValue);
bufferSize = sizeof(double);
pBuffer = Marshal.AllocCoTaskMem(bufferSize);
Marshal.StructureToPtr(value, pBuffer, false);
}
if (fieldType == typeof(string))
{
bufferSize = bstrValue.Length;
pBuffer = Marshal.StringToCoTaskMemAuto(bstrValue);
}
if (bufferSize != 0)
{
byte[] byteBuffer = new byte[bufferSize];
for (int i = 0; i < bufferSize; i++)
{
byteBuffer[i] = Marshal.ReadByte(pBuffer,i);
}
Marshal.FreeCoTaskMem(pBuffer);
hr = valueObject.SetValue(byteBuffer, (uint)bufferSize);
}
}
}
return hr;
}
}
}
codice non gestito
Si tratta di un'implementazione di IDebugProperty2::SetValueAsString nel codice gestito. La funzione di supporto FieldCoerceValueType (non mostrato) potrebbe VARIANT a un tipo specifico e che garantisce che il valore sia uno dei tipi FieldSetValue possibile gestire.
[C++]
STDMETHODIMP CFieldProperty::SetValueAsString(
in LPCOLESTR pszValueStr,
in DWORD radix,
in DWORD timeout
)
{
HRESULT hr;
//evaluate the value
VARIANT value;
hr = Evaluate( m_provider,
m_address,
m_binder,
pszValueStr,
NULL,
&value );
if (FAILED(hr))
return hr;
if (hr == S_FALSE)
return E_FAIL; //parse failed
//copy the bits
hr = FieldSetValue( m_binder, m_field, value );
return hr;
}
//----------------------------------------------------------------------------
HRESULT FieldSetValue(
in IDebugBinder* pbinder,
in IDebugField* pfield,
in VARIANT& rawValue )
{
if (pfield == NULL)
return E_INVALIDARG;
if (pbinder == NULL)
return E_INVALIDARG;
HRESULT hr = S_OK;
IDebugObject* pobject = NULL;
VARIANT value;
VariantInit(&value);
//check the type
hr = FieldCoerceValueType( pbinder, pfield, rawValue, &value );
if (FAILED(hr))
goto fail;
if (hr == S_FALSE)
{
VariantClear(value);
return E_FAIL;
}
//get the object
hr = pbinder->Bind( NULL, pfield, &pobject );
if (FAILED(hr))
{
pobject->Release();
VariantClear(value);
return hr;
}
//set the value
switch (value.vt)
{
case VT_BSTR:
{
if (value.bstrVal == NULL)
{
LPOLESTR pszEmptyStr = OLE("");
hr = pobject->SetValue( reinterpret_cast<BYTE*>(pszEmptyStr),
sizeof(OLECHAR) );
}
else
hr = pobject->SetValue( reinterpret_cast<BYTE*>(value.bstrVal),
(SysStringLen(value.bstrVal)+1) * sizeof(wchar_t));
}
case VT_BOOL:
case VT_I1:
case VT_UI1:
hr = pobject->SetValue( reinterpret_cast<BYTE*>(&(value.byref)), 1 );
break;
case VT_I2:
case VT_UI2:
hr = pobject->SetValue( reinterpret_cast<BYTE*>(&(value.byref)), 2 );
break;
case VT_I4:
case VT_UI4:
case VT_R4:
hr = pobject->SetValue( reinterpret_cast<BYTE*>(&(value.byref)), 4 );
break;
case VT_I8:
case VT_UI8:
case VT_R8:
hr = pobject->SetValue( reinterpret_cast<BYTE*>(&(value.byref)), 8 );
break;
case VT_VOID:
case VT_EMPTY:
hr = E_FAIL;
break;
case VT_UNKNOWN:
{
//this is also a field (structured type)
if (value.punkVal == NULL)
{
pobject->Release();
VariantClear(value);
return E_FAIL;
};
IDebugField* valueField;
hr = value.punkVal->QueryInterface( IID_IDebugField,
reinterpret_cast<void**>(&valueField) );
if (FAILED(hr))
{
pobject->Release();
VariantClear(value);
return hr;
};
//for MyC we simply copy the bits
IDebugObject* valueObject;
hr = pbinder->Bind( NULL, valueField, &valueObject );
valueField->Release();
if (FAILED(hr))
{
pobject->Release();
VariantClear(value);
return hr;
};
BYTE* pvalueBits;
UINT valueSize;
hr = valueObject->GetSize( &valueSize );
if (FAILED(hr))
{
valueObject->Release();
pobject->Release();
VariantClear(value);
return hr;
};
pvalueBits = NALLOC(BYTE,valueSize+1);
if (!pvalueBits)
{
valueObject->Release();
pobject->Release();
VariantClear(value);
return E_OUTOFMEMORY;
};
hr = valueObject->GetValue( pvalueBits, valueSize );
valueObject->Release();
if (FAILED(hr))
{
free(pvalueBits);
pobject->Release();
VariantClear(value);
return hr;
}
hr = pobject->SetValue( pvalueBits, valueSize );
free(pvalueBits);
if (FAILED(hr))
{
pobject->Release();
VariantClear(value);
return hr;
}
break;
}
default:
//not a primitive type
hr = E_FAIL;
break;
}
VariantClear( &value );
pobject->Release();
return hr;
}