IDebugProperty2:: GetPropertyInfo 调用以获取本地的值,以及本地的名称和类型。 因为本地的值依赖于程序的当前状态,必须从内存获取本地的值。 IDebugBinder 对象用于绑定表示本地的 IDebugField 对象对包含该值的内存中的相应位置。 内存的此位置由 IDebugObject 对象表示。
检索本地值的此函数在执行以下任务的帮助器函数来封装:
绑定到内存的 IDebugField 对象获取 IDebugObject 对象。
从内存获取该值。 此值表示为一系列字节。
设置基于本地的类型。
返回包含本地值的泛型对象。 在 c# 中,这是 object,因此,在 C++ 中,这是 VARIANT。
托管代码
这是检索本地的值在托管代码的函数的实现。
namespace EEMC
{
internal class Field
{
internal static object GetValue(
IDebugBinder binder,
IDebugField field,
Type t,
uint size)
{
if (t == null || size == 0) return null;
IDebugObject debugObject = null;
binder.Bind(null, field, out debugObject);
byte[] buffer = new byte[size];
for (int i = 0; i < size; i++) buffer[i] = 0;
debugObject.GetValue(buffer, size);
if (t == typeof(sbyte)) return (sbyte) buffer[0];
if (t == typeof(short)) return BitConverter.ToInt16(buffer, 0);
if (t == typeof(int)) return BitConverter.ToInt32(buffer, 0);
if (t == typeof(long)) return BitConverter.ToInt64(buffer, 0);
if (t == typeof(byte)) return buffer[0];
if (t == typeof(char)) return BitConverter.ToChar(buffer, 0);
if (t == typeof(uint)) return BitConverter.ToUInt32(buffer, 0);
if (t == typeof(ulong)) return BitConverter.ToUInt64(buffer, 0);
if (t == typeof(float)) return BitConverter.ToSingle(buffer, 0);
if (t == typeof(double)) return BitConverter.ToDouble(buffer, 0);
if (t == typeof(bool)) return BitConverter.ToBoolean(buffer, 0);
if (t == typeof(string)) return BitConverter.ToString(buffer, 0);
return null;
}
}
}
非托管代码
这是检索本地的值在非托管代码的函数的实现。 FieldGetType 在 获取本地值显示。
HRESULT FieldGetPrimitiveValue(
in IDebugBinder* pbinder,
in IDebugField* pfield,
out VARIANT* pvarValue
)
{
if (pvarValue == NULL)
return E_INVALIDARG;
else
*pvarValue = 0;
if (pfield == NULL)
return E_INVALIDARG;
if (pbinder == NULL)
return E_INVALIDARG;
HRESULT hr;
UINT valueSize = 0;
BYTE* pvalueBits = NULL;
IDebugObject* pobject = NULL;
//get the value as bits
hr = pbinder->Bind( NULL, pfield, &pobject );
if (FAILED(hr))
return hr;
hr = pobject->GetSize( &valueSize );
if (FAILED(hr))
{
pobject->Release();
return hr;
}
pvalueBits = reinterpret_cast<BYTE *>(malloc(valueSize * sizeof(BYTE)));
if (!pvalueBits)
{
pobject->Release();
return E_OUTOFMEMORY;
}
hr = pobject->GetValue( pvalueBits, valueSize );
pobject->Release();
if (FAILED(hr))
{
free(pvalueBits);
return hr;
}
//get the type
VARIANT valueType;
hr = FieldGetType( pfield, &valueType );
if (FAILED(hr))
{
free(pvalueBits);
return hr;
}
//copy a primitive value
switch (valueType.vt)
{
case VT_BSTR:
{
pvarValue->vt = VT_BSTR;
if (valueSize == 0)
pvarValue->bstrVal = SysAllocString( OLE("") );
else
pvarValue->bstrVal =
SysAllocStringByteLen( reinterpret_cast<char*>(pvalueBits),
valueSize );
}
case VT_BOOL:
case VT_I1:
case VT_I2:
case VT_I4:
case VT_I8:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_UI8:
case VT_R4:
case VT_R8:
pvarValue->vt = valueType.vt;
if (valueSize > 8)
valueSize = 8;
memcpy( &(pvarValue->iVal), pvalueBits, valueSize );
break;
case VT_VOID:
case VT_EMPTY:
pvarValue->vt = valueType.vt;
break;
default:
//not a primitive type
VariantClear(&valueType);
free(pvalueBits);
return E_FAIL;
}
free(pvalueBits);
VariantClear(&valueType);
return S_OK;
}