2013-12-16 4 views
1

Я использую интерфейс ITypeInfo для получения информации о COM-объектах и ​​их членах (для создания своего рода API отображения). Чтение типов и элементов (и их параметров) отлично работает, но я не знаю, как получить доступ к значению по умолчанию параметра. Это то, что у меня есть ...Как получить значение по умолчанию от PARAMDESC

... 

PARAMDESC paramDesc = elemDesc.desc.paramdesc; 

object defaultValue = null; 
PARAMFLAG paramFlags = paramDesc.wParamFlags; 
bool hasDefaultValue = (paramFlags & PARAMFLAG.PARAMFLAG_FHASDEFAULT) == PARAMFLAG.PARAMFLAG_FHASDEFAULT; 
if (hasDefaultValue && paramDesc.lpVarValue != IntPtr.Zero) 
{ 
    defaultValue = null; // TODO: get value from paramDesc.lpVarValue 
} 

... 

Я проверяю wParamFlags поле; если параметр имеет значение по умолчанию, а поле lpVarValue имеет действительный указатель, я хотел бы прочитать это значение. Я предположил, что lpVarValue указывает на родной COM вариант, поэтому я попытался получить объект, представляющий значение по умолчанию с помощью Marshal.GetObjectForNativeVariant, но это не удается с фатальной ошибкой ...

ответ

2

Они взяли ярлык на PARAMDESC.lpVarValue, потому что тип указателя трудно объявить в управляемом коде. Это на самом деле указатель на PARAMDESCEX, объявленный как это в oaidl.idl:

typedef struct tagPARAMDESCEX { 
    ULONG cBytes;    /* size of this structure */ 
    VARIANTARG varDefaultValue; /* default value of this parameter */ 
} PARAMDESCEX, * LPPARAMDESCEX; 

Так что, да, используя Marshal.GetObjectForNativeVariant() является хорошим способом, чтобы получить varDefaultValue поле. Однако вы должны добавить, чтобы пропустить поле cBytes. Это требует добавления 4, чтобы пропустить ULONG и еще 4, чтобы пропустить отступы между полями. Поэтому используйте что-то вроде:

PARAMDESC pd = ...; 
object defValue = null; 
if ((pd.wParamFlags & 0x20) != 0) { 
    IntPtr defptr = new IntPtr((long)pd.lpVarValue + 8); 
    defValue = Marshal.GetObjectForNativeVariant(defptr); 
} 
+0

Это решение работает. Единственное, что я изменил, это смещение указателя ... isn't ulong 8-байтовое целое? – Matze

+0

Нет, его 4 байта. Оба в 32-битном и 64-битном режимах. –

+0

Но если я использую 4 байта, он продолжает сбой ... – Matze

0

documentation для PARAMFLAG_FHASDEFAULT говорит:

Параметр имеет поведение по умолчанию. Поле pPARAMDescEx содержит указатель на VARIANT, который описывает значение по умолчанию для этого параметра, если установлен бит PARAMFLAG_FOPT и PARAMFLAG_FHASDEFAULT из wParamFlags.

Таким образом, до тех пор, как PARAMFLAG_FOPT и PARAMFLAG_FHASDEFAULT установлены, вы можете прочитать информацию из paramDesc.pPARAMDescEx.


Но согласно ответу от @Hans, это на самом деле PARAMDESCEX, а не PARAMDESC и, следовательно, мое замешательство.

Смежные вопросы