所以我试图使用上面的属性获取SMTP地址属性。但是我得到了算术溢出。
基本使用:
IUnknown = Marshal.GetIUnknownForObject(recipientAddress.MAPIOBJECT);
HrGetOneProp(IMAPIProperty, PR_EMS_AB_PROXY_ADDRESSES, ref pPropValue);
SPropValue propValue = (SPropValue)Marshal.PtrToStructure(pPropValue, typeof(SPropValue));
IntPtr ptrToConvert = new IntPtr(propValue.Value); //arithmetic overflow
sProperty = Marshal.PtrToStringAnsi(ptrToConvert);
我创建的结构是:
private struct SPropValue {
public unit ulPropTag
public uint dwAlignPad
public long Value
}
我认为问题出在结构上:http://msdn.microsoft.com/en-us/library/bb415341.aspx
问题是,propValue.Value真的很"长",不适合IntPtr,我认为这个结构实际上是SPropValue结构的指针,
所以我真的不知道如何使用它以及如何解决这个问题。
任何帮助都会被告知。。。
**编辑**我试图创建一个联合PV类,从c++开始,这就是联合类:
typedef union _PV
{
short int i; /* case PT_I2 */
LONG l; /* case PT_LONG */
ULONG ul; /* alias for PT_LONG */
float flt; /* case PT_R4 */
double dbl; /* case PT_DOUBLE */
unsigned short int b; /* case PT_BOOLEAN */
CURRENCY cur; /* case PT_CURRENCY */
double at; /* case PT_APPTIME */
FILETIME ft; /* case PT_SYSTIME */
...
...
所以我创建了这个结构:
[StructLayout(LayoutKind.Explicit)]
private struct PV_Union
{
[FieldOffset(0)]
public Int16 i; /* case PT_I2 */
[FieldOffset(0)]
public Int32 l; /* case PT_LONG */
[FieldOffset(0)]
public UInt32 ul; /* alias for PT_LONG */
....
现在我得到了垃圾价值。。
SPropValue.value结构是一个并集,这意味着成员相互重叠。
为什么不使用AddressEntry.PropertyAccessor.GetProperty来检索属性?
所以我设法解决了它!我来解释。Value实际上是并集类型,我确实找到了正确的内存区域,但读错了。
当我们读取这个内存区域时,我们得到以下内容:
- uint表示"值"类型和命令,我将其分为2个ushort(第一个-较高的位是返回的类型:PT_MV_TSTRINGS,它等于MV_FLAGS | PT_UNICODE(多值+UNICODE字符串)
- dwAlignedPad的uint
- SWStringArray-它是实际的"Value",它有数组长度的uint,后面跟着实际字符串数组的uint(指向数组指针的指针)
所以我创建了以下结构,并将HrGetOneProp读取到其中:
private struct SMultivalueStructure
{
public ushort PropType; // Type of returned value
public ushort Command; //Command we entered (PR_EMS_PROXY...)
public uint dwAlignPad; // Reserved - usually 4 bytes of 0
public uint stringArrayLength; // SWStringArray length
public uint pStringArrayMemoryAddress; //SWStringArray pointer to string array
}
所以在元帅之后
SMultivalueStructure propValue = (SMultivalueStructure)Marshal.PtrToStructure(pPropValue, typeof(SMultivalueStructure));
我创建了一个长度正确的指针数组来保存指向字符串的指针:
IntPtr[] pStrings = new IntPtr[propValue.stringArrayLength];
然后我在结构中有字符串数组的内存地址,所以我会将指针复制到我刚刚创建的数组中:
Marshal.Copy(new IntPtr(propValue.pStringArrayMemoryAddress), pStrings, 0, (int)propValue.stringArrayLength);
现在我有了每个字符串的内存地址数组,现在只需将其封送到字符串:
for (int i = 0; i < pStrings.Length; ++i)
{
string smtpTest = Marshal.PtrToStringAnsi(pStrings[i]);
}
顺便说一下,字符串数组可以是两个可能的值:(http://msdn.microsoft.com/en-us/library/bb446176.aspx)
- PT_MV_STRING8-SLPSTRArray
- PT_MV_UNICODE-SWStringArray
所以我添加了一个检查(针对PropType)-ANSI字符串应该是MV_FLAG|PT_STRING8,UNICODE应该是MV-FLAG|PT_UNICODE,然后使用正确的MarshalPtrToStringAnsi/Uni
我需要检查的几个问题:
- 在64位outlook中-这段代码可以吗?还是我必须以不同的方式处理
- 检查每个outlook版本(2003200720102010 64位)